1. 程式人生 > >MyBatis(1)-- MyBatis介紹

MyBatis(1)-- MyBatis介紹

結果 .com mes resources role factor 動態sql ons 關於

  一、MyBatis優點

  • 不屏蔽SQL,意味著可以更為精確地定位SQL語句,可以對其進行優化和改造,這有利於互聯網系統性能的提高,符合互聯網需要性能優化的特點。
  • 提供強大、靈活的映射機制,方便Java開發者使用。提供動態SQL的功能,允許我們根據不同條件組裝SQL,這個功能遠比其他工具或者Java編碼的可讀性和可維護性高得多,滿足各種應用系統的同時也滿足了需求經常變化的互聯網應用的要求。
  • 在MyBatis中,提供了使用Mapper的接口編程,只要一個接口和一個XML就能創建映射器,進一步簡化我們的工作,使得很多框架API在MyBatis中消失,開發者能更集中於業務邏輯。

  

  二、MyBatis核心組件

  技術分享圖片

  • SqlSessionFactoryBuilder(構造器):它會根據配置或者代碼來生成SqlSessionFactory,采用的是分步構建的Builder模式
  • SqlSessionFactory(工廠接口):依靠它來生成SqlSession,使用的是工廠模式。
  • SqlSession(會話):一個既可以發送SQL執行返回結果,也可以獲取Mapper的接口。一般使用MyBatis提供的SQL Mapper接口編程技術,能提高代碼的可讀性和可維護性。
  • SQL Mapper(映射器):由一個Java接口和XML文件(或註解)構成,需要給出對應的SQL和映射規則。它負責發送SQL去執行,並返回結果。

  三、MyBatis運行流程圖

  技術分享圖片

  四、搭建MyBatis開發環境

  1.新建MySQL表

mysql> select * from t_role;
+----+-------------+--------+
| id | role_name | note |
+----+-------------+--------+
| 1 | role_name_1 | note_1 |
+----+-------------+--------+
1 row in set (0.00 sec)

  2.文件布局

  技術分享圖片

  3.SQLSessionFactory(工廠接口)

  構建SQLSessionFactory有兩種方法:使用XML構建SqlSessionFactory;使用Java代碼構建SqlSessionFactory

  (1)使用XML構建SqlSessionFactory

    MyBatis基礎配置文件mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration   PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <typeAliases><!-- 別名 -->
      <typeAlias alias="role" type="com.mybatis.pojo.Role"/>
  </typeAliases>
  <!-- 數據庫環境 -->
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis_test?useSSL=false"/>
        <property name="username" value="root"/>
        <property name="password" value="bjtungirc"/>
      </dataSource>
    </environment>
  </environments>
  <!-- 映射文件 -->
  <mappers>
    <mapper resource="com/mybatis/mapper/RoleMapper.xml"/>
    <mapper class="com.mybatis.mapper.RoleMapper2"/> 
  </mappers>
</configuration>

  基礎配置文件的作用是配置一些最基本的上下文參數和運行環境。

  • <typeAliases>元素定義了一個別名role,它代表著com.mybatis.pojo.Role這個類。這樣定義後,就可以在MyBatis上下文中使用別名role去代替全限定名com.mybatis.pojo.Role了。
  • <environments>用來定義數據庫環境。<transactionManager>配置事務管理器為JDBC方式,<dataSource>用來配置數據庫,其中type="POOLED"代表采用MyBatis內部提供的連接池方式。
  • <mapper>元素代表引入的那些映射器。

  有了基礎配置文件,就可以用一段很簡短的代碼生成SqlSessionFactory了。

  即首先讀取mybatis-config.xml,然後通過SqlSessionFactoryBuilderbuild方法啟用創建SqlSessionFactory。

  采用XML創建的形式,信息在配置文件中,有利於我們日後的維護和修改,避免了重新編譯代碼,因此推薦這種方式創建SqlSessionFactory。

    // 使用XML構建SQLSessionFactory
    public static SqlSessionFactory getSqlSessionFactory() {
        synchronized (LOCK) {
            if (sqlSessionFactory != null) {
                return sqlSessionFactory;
            }
            String resource = "mybatis-config.xml";
            InputStream inputStream;
            try {
                inputStream = Resources.getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
            return sqlSessionFactory;
        }
    }

  (2)使用Java代碼構建SqlSessionFactory

  使用Java代碼創建SqlSessionFactory的代碼冗長,如果發生系統修改,那麽有可能需要重新編譯代碼帶能繼續,所以這不是一個很好的方式。除非有特殊的需求,比如在配置文件中,需要配置加密過的數據庫用戶名和密碼,需要我們在生成SqlSessionFactory前解密為明文的時候,才會考慮使用這種方式。

    // 使用代碼創建SQLSessionFactory
    public static SqlSessionFactory getSqlSessionFactory2() {
        synchronized (LOCK) {
            // 數據庫連接池信息
            PooledDataSource dataSource = new PooledDataSource();
            dataSource.setDriver("com.mysql.jdbc.Driver");
            dataSource.setUsername("root");
            dataSource.setPassword("bjtungirc");
            dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis_test?useSSL=false");
            dataSource.setDefaultAutoCommit(false);
            // 采用MyBatis的JDBC事務方式
            TransactionFactory transactionFactory = new JdbcTransactionFactory();
            Environment environment = new Environment("development", transactionFactory, dataSource);
            // 創建Configuration對象
            Configuration configuration = new Configuration(environment);
            // 註冊一個MyBatis上下文別名
            configuration.getTypeAliasRegistry().registerAlias("role", Role.class);
            // 加入一個映射器
            configuration.addMapper(RoleMapper.class);
            configuration.addMapper(RoleMapper2.class);
            // 使用SQLSessionFactoryBuilder構建sqlSessionFactory
            sqlSessionFactory = 
                new SqlSessionFactoryBuilder().build(configuration);
            return sqlSessionFactory;     
        }
    }

  (3)SqlSessionFactory作為一個單例

  SqlSessionFactory可以被認為是一個數據庫連接池,它的作用是創建SqlSession接口對象。因為MyBatis的本質就是Java對數據庫的操作,所以SqlSessionFactory的生命周期存在於整個MyBatis的應用之中,所以一旦創建了SqlSessionFactory,就要長期保存它,直至不再使用MyBatis應用,所以可以認為SqlSessionFactory的生命周期就等同於MyBatis的應用周期。

  由於SqlSessionFactory是一個對數據庫的連接池,所以它占據著數據庫的連接資源,如果創建多個SqlSessionFactory,那麽就存在多個數據庫連接池,這樣不利於對數據庫資源的控制,也會導致數據庫連接資源被消耗光,出現系統宕機的情況,所以在一般的應用中往往希望SqlSessionFactory作為一個單例,讓它在應用中被共享。

package com.mybatis.utils;
public class SqlSessionFactoryUtils {

    private final static Class<SqlSessionFactoryUtils> LOCK = SqlSessionFactoryUtils.class;

    private static SqlSessionFactory sqlSessionFactory = null;

    private SqlSessionFactoryUtils() {
    }

    // 使用XML構建SQLSessionFactory
    public static SqlSessionFactory getSqlSessionFactory() {
        synchronized (LOCK) {
       ...
     return sqlSessionFactory;
} } // 使用代碼創建SQLSessionFactory public static SqlSessionFactory getSqlSessionFactory2() { synchronized (LOCK) { // 數據庫連接池信息        ...return sqlSessionFactory; } } public static SqlSession openSqlSession() { if (sqlSessionFactory == null) { getSqlSessionFactory(); } return sqlSessionFactory.openSession(); } }

  SqlSessionFactoryUtils的構造方法中加入了private關鍵字,使得其他代碼不能通過new的方式來創建它。同時加入synchronized關鍵字加鎖,主要是為了防止在多線程中多次實例化SqlSessionFactory對象,從而保證SqlSessionFactory的唯一性。而openSqlSession方法使用叠代來創建SqlSession對象。

  4.SQLSession(會話)

  在MyBatis中有兩個實現類,DefaultSqlSession和SqlSessionManager。其中DefaultSqlSession是單線程使用的,而SqlSessionManager是在多線程環境下使用。SqlSession的作用類似於一個JDBC中的Connection對象,代表著一個連接資源的啟用。它的作用有三個:獲取Mapper接口--發送SQL給數據庫--控制數據庫事務

    private static void testRoleMapper() {
        Logger log = Logger.getLogger(Main.class);
        SqlSession sqlSession = null;
        try {
            sqlSession = SqlSessionFactoryUtils.openSqlSession();
            RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
            Role role = roleMapper.getRole(1L);
            log.info(role.getRoleName());
        } finally {
            // 在finally語句中確保資源被順利關閉
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

  有了映射器就可以通過SqlSession發送SQL了,有兩種方式:一種是通過SqlSession直接發送,另外一種是通過SqlSession獲取Mapper接口再發送。

  (1)使用SqlSession直接發送

Role role = (role)sqlSession.selectOne("com.mybatis.mapper.RoleMapper.getRole", 1L);

  selectOne方法表示使用查詢並且只返回一個對象,而參數則是一個String對象和一個Object對象。

  (2)使用SqlSession獲取Mapper接口再發送

            RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
            Role role = roleMapper.getRole(1L);

  通過SqlSession的getMapper方法來獲取一個Mapper接口,就可以調用它的方法了。

  使用Mapper接口編程可以消除SqlSession帶來的功能性代碼,提高可讀性,更能體現業務的邏輯,因此推薦這種方式。

  5.SQL Mapper(映射器)

  映射器是MyBatis中最重要、最復雜的組件,它由一個接口和對應的XML文件(或註解組成)。可以配置下列內容:

  • 描述映射規則
  • 提供SQL語句,並可以配置SQL參數類型、返回類型、緩存刷新等信息
  • 配置緩存
  • 提供動態SQL

  實現映射器有兩種方式,即XML文件形式和註解形式。首先定義一個POJO,

package com.mybatis.pojo;

public class Role {

    private Long id;
    private String roleName;
    private String note;

    /** setter and getter **
}

  映射器的主要作用就是將SQL查詢到的結果映射為一個POJO,或者將POJO的數據插入到數據庫中,並定義一些關於緩存等的重要內容。

  而映射器的只是一個接口類,為什麽不是實現類,這是因為MyBatis運用了動態代理技術使得接口能夠運行起來,MyBatis會為這個接口生成一個代理對象,代理對象回去處理相關的邏輯。

  (1)使用XML實現映射器

    使用XML實現映射器分為兩個部分:接口+XML.

package com.mybatis.mapper;import com.mybatis.pojo.Role;

public interface RoleMapper {public Role getRole(Long id);
}

  在使用XML方式創建SqlSessionFactory的配置文件mybatis-config.xml中使用下面的代碼引入一個XML文件,

<mapper resource="com/mybatis/mapper/RoleMapper.xml"/>

  在使用Java代碼創建SqlSessionFactory的時候,使用下面的語句註冊一個mapper

configuration.addMapper(RoleMapper.class);

  RoleMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mybatis.mapper.RoleMapper">

    <select id="getRole" parameterType="long" resultType="role">
        select id,
        role_name as roleName, note from t_role where id = #{id}
    </select>

</mapper>

  其中namespace所對應的是一個接口的全限定名,<select>元素表明這是一條查詢語句,而屬性id標識了這條SQL,parameterType="long"說明傳遞給SQL的是一個long型的參數,而resultType="role"說明返回的是一個role類型的返回值,這裏的role是mybatis-config.xml中配置的別名,語句中的#{id}表示傳遞進去的參數。

  (2)使用註解實現映射器

package com.mybatis.mapper;

import org.apache.ibatis.annotations.Select;

import com.mybatis.pojo.Role;


public interface RoleMapper2 {
    
    @Select("select id, role_name as roleName, note from t_role where id=#{id}")
    public Role getRole(Long id);
}

  在使用XML方式創建SqlSessionFactory的配置文件mybatis-config.xml中使用下面的代碼引入一個Class文件,

<mapper class="com.mybatis.mapper.RoleMapper2"/> 

  在使用Java代碼創建SqlSessionFactory的時候,使用下面的語句註冊一個mapper

configuration.addMapper(RoleMapper2.class);

  6.日誌輸出環境配置文件log4j.properties

log4j.rootLogger=DEBUG , stdout
log4j.logger.org.mybatis=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%n

  配置信息:日誌輸出級別為DEBUG,並且輸出端載體是ConsoleAppender即控制臺類型,且輸出端載體的界面布局為自定義布局,最後一行是布局的自定義格式。

  

MyBatis(1)-- MyBatis介紹