【Java開源框架】持久層框架mybatis與spring/spring boot整合

什麼是 MyBatis-Spring?

MyBatis-Spring 會幫助你將 MyBatis 代碼無縫地整合到 Spring 中。它將允許 MyBatis 參與到 Spring 的事務管理之中,創建映射器 mapper 和 SqlSession 並注入到 bean 中,以及將 Mybatis 的異常轉換爲 Spring 的 DataAccessException。最終,可以做到應用代碼不依賴於 MyBatis,Spring 或 MyBatis-Spring。

Spring 2.0 只支持 iBatis 2.0。那麼,我們就想將 MyBatis3 的支持添加到 Spring 3.0 中(參見 Spring Jira 中的問題)。不幸的是,Spring 3.0 的開發在 MyBatis 3.0 官方發佈前就結束了。由於 Spring 開發團隊不想發佈一個基於未發佈版的 MyBatis 的整合支持,如果要獲得 Spring 官方的支持,只能等待下一次的發佈了。基於在 Spring 中對 MyBatis 提供支持的興趣,MyBatis 社區認爲,應該開始召集有興趣參與其中的貢獻者們,將對 Spring 的集成作爲 MyBatis 的一個社區子項目。

知識基礎

在開始使用 MyBatis-Spring 之前,你需要先熟悉 Spring 和 MyBatis 這兩個框架和有關它們的術語。這很重要——因爲本手冊中不會提供二者的基本內容,安裝和配置教程。

MyBatis-Spring 需要以下版本:

MyBatis-Spring MyBatis Spring 框架 Spring Batch Java
2.0 3.5+ 5.0+ 4.0+ Java 8+
1.3 3.4+ 3.2.2+ 2.1+ Java 6+

安裝

要使用 MyBatis-Spring 模塊,只需要在類路徑下包含 mybatis-spring-2.0.1.jar 文件和相關依賴即可。

如果使用 Maven 作爲構建工具,僅需要在 pom.xml 中加入以下代碼即可:

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>2.0.1</version>
</dependency>

快速上手

要和 Spring 一起使用 MyBatis,需要在 Spring 應用上下文中定義至少兩樣東西:一個 SqlSessionFactory 和至少一個數據映射器類。

在 MyBatis-Spring 中,可使用 SqlSessionFactoryBean來創建 SqlSessionFactory。 要配置這個工廠 bean,只需要把下面代碼放在 Spring 的 XML 配置文件中:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
</bean>
@Bean
public SqlSessionFactoryBean sqlSessionFactory() throws Exception {
  SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
  factoryBean.setDataSource(dataSource());
  return factoryBean.getObject();
}

注意:SqlSessionFactory 需要一個 DataSource(數據源)。 這可以是任意的 DataSource,只需要和配置其它 Spring 數據庫連接一樣配置它就可以了。

假設你定義了一個如下的 mapper 接口:

public interface UserMapper {
  @Select("SELECT * FROM users WHERE id = #{userId}")
  User getUser(@Param("userId") String userId);
} 

那麼可以通過 MapperFactoryBean 將接口加入到 Spring 中:

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
  <property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

需要注意的是:所指定的映射器類必須是一個接口,而不是具體的實現類。在這個示例中,通過註解來指定 SQL 語句,但是也可以使用 MyBatis 映射器的 XML 配置文件。

配置好之後,你就可以像 Spring 中普通的 bean 注入方法那樣,將映射器注入到你的業務或服務對象中。MapperFactoryBean 將會負責 SqlSession 的創建和關閉。如果使用了 Spring 的事務功能,那麼當事務完成時,session 將會被提交或回滾。最終任何異常都會被轉換成 Spring 的 DataAccessException 異常。

使用 Java 代碼來配置的方式如下:

@Bean
public UserMapper userMapper() throws Exception {
  SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory());
  return sqlSessionTemplate.getMapper(UserMapper.class);
}

要調用 MyBatis 的數據方法,只需一行代碼:

public class FooServiceImpl implements FooService {

  private final UserMapper userMapper;

  public FooServiceImpl(UserMapper userMapper) {
    this.userMapper = userMapper;
  }

  public User doSomeBusinessStuff(String userId) {
    return this.userMapper.getUser(userId);
  }
}

SqlSessionFactoryBean

在基礎的 MyBatis 用法中,是通過 SqlSessionFactoryBuilder 來創建 SqlSessionFactory 的。 而在 MyBatis-Spring 中,則使用 SqlSessionFactoryBean 來創建。

設置

要創建工廠 bean,將下面的代碼放到 Spring 的 XML 配置文件中:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
</bean>

需要注意的是 SqlSessionFactoryBean 實現了 Spring 的 FactoryBean 接口(參見 Spring 官方文檔 3.8 節 通過工廠 bean 自定義實例化邏輯)。這意味着由 Spring 最終創建的 bean 並不是 SqlSessionFactoryBean 本身,而是工廠類(SqlSessionFactoryBean)的 getObject() 方法的返回結果。這種情況下,Spring 將會在應用啓動時爲你創建 SqlSessionFactory,並使用 sqlSessionFactory 這個名字存儲起來。

等效的 Java 代碼如下:

@Bean
public SqlSessionFactory sqlSessionFactory() {
  SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
  factoryBean.setDataSource(dataSource());
  return factoryBean.getObject();
}

通常,在 MyBatis-Spring 中,你不需要直接使用 SqlSessionFactoryBean 或對應的 SqlSessionFactory。相反,session 的工廠 bean 將會被注入到 MapperFactoryBean 或其它繼承於 SqlSessionDaoSupport 的 DAO(Data Access Object,數據訪問對象)中。

屬性

SqlSessionFactory 有一個唯一的必要屬性:用於 JDBC 的 DataSource。這可以是任意的 DataSource 對象,它的配置方法和其它 Spring 數據庫連接是一樣的。

一個常用的屬性是 configLocation,它用來指定 MyBatis 的 XML 配置文件路徑。它在需要修改 MyBatis 的基礎配置非常有用。通常,基礎配置指的是 <settings> 或 <typeAliases> 元素。

需要注意的是,這個配置文件並不需要是一個完整的 MyBatis 配置。確切地說,任何環境配置(<environments>),數據源(<DataSource>)和 MyBatis 的事務管理器(<transactionManager>)都會被忽略。SqlSessionFactoryBean 會創建它自有的 MyBatis 環境配置(Environment),並按要求設置自定義環境的值。

如果 MyBatis 在映射器類對應的路徑下找不到與之相對應的映射器 XML 文件,那麼也需要配置文件。這時有兩種解決辦法:第一種是手動在 MyBatis 的 XML 配置文件中的 <mappers> 部分中指定 XML 文件的類路徑;第二種是設置工廠 bean 的 mapperLocations 屬性。

mapperLocations 屬性接受多個資源位置。這個屬性可以用來指定 MyBatis 的映射器 XML 配置文件的位置。屬性的值是一個 Ant 風格的字符串,可以指定加載一個目錄中的所有文件,或者從一個目錄開始遞歸搜索所有目錄。比如:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="mapperLocations" value="classpath*:sample/config/mappers/**/*.xml" />
</bean>

這會從類路徑下加載所有在 sample.config.mappers 包和它的子包中的 MyBatis 映射器 XML 配置文件。

在容器管理事務的時候,你可能需要的一個屬性是 transactionFactoryClass。請參考事務一章的相關章節。

如果你使用了多個數據庫,那麼需要設置 databaseIdProvider 屬性:

<bean id="databaseIdProvider" class="org.apache.ibatis.mapping.VendorDatabaseIdProvider">
  <property name="properties">
    <props>
      <prop key="SQL Server">sqlserver</prop>
      <prop key="DB2">db2</prop>
      <prop key="Oracle">oracle</prop>
      <prop key="MySQL">mysql</prop>
    </props>
  </property>
</bean>

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="mapperLocations" value="classpath*:sample/config/mappers/**/*.xml" />
  <property name="databaseIdProvider" ref="databaseIdProvider"/>
</bean>

提示 自 1.3.0 版本開始,新增的 configuration 屬性能夠在沒有對應的 MyBatis XML 配置文件的情況下,直接設置 Configuration 實例。例如:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="configuration">
    <bean class="org.apache.ibatis.session.Configuration">
      <property name="mapUnderscoreToCamelCase" value="true"/>
    </bean>
  </property>
</bean>

事務

一個使用 MyBatis-Spring 的其中一個主要原因是它允許 MyBatis 參與到 Spring 的事務管理中。而不是給 MyBatis 創建一個新的專用事務管理器,MyBatis-Spring 藉助了 Spring 中的 DataSourceTransactionManager 來實現事務管理。

一旦配置好了 Spring 的事務管理器,你就可以在 Spring 中按你平時的方式來配置事務。並且支持 @Transactional 註解和 AOP 風格的配置。在事務處理期間,一個單獨的 SqlSession 對象將會被創建和使用。當事務完成時,這個 session 會以合適的方式提交或回滾。

事務配置好了以後,MyBatis-Spring 將會透明地管理事務。這樣在你的 DAO 類中就不需要額外的代碼了。

標準配置

要開啓 Spring 的事務處理功能,在 Spring 的配置文件中創建一個 DataSourceTransactionManager 對象:

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <constructor-arg ref="dataSource" />
</bean>
@Bean
public DataSourceTransactionManager transactionManager() {
  return new DataSourceTransactionManager(dataSource());
}

傳入的 DataSource 可以是任何能夠與 Spring 兼容的 JDBC DataSource。包括連接池和通過 JNDI 查找獲得的 DataSource。

注意:爲事務管理器指定的 DataSource 必須和用來創建 SqlSessionFactoryBean 的是同一個數據源,否則事務管理器就無法工作了。

交由容器管理事務

如果你正使用一個 JEE 容器而且想讓 Spring 參與到容器管理事務(Container managed transactions,CMT)的過程中,那麼 Spring 應該被設置爲使用 JtaTransactionManager 或由容器指定的一個子類作爲事務管理器。最簡單的方式是使用 Spring 的事務命名空間或使用 JtaTransactionManagerFactoryBean:

<tx:jta-transaction-manager />
@Bean
public JtaTransactionManager transactionManager() {
  return new JtaTransactionManagerFactoryBean().getObject();
}

在這個配置中,MyBatis 將會和其它由容器管理事務配置的 Spring 事務資源一樣。Spring 會自動使用任何一個存在的容器事務管理器,並注入一個 SqlSession。如果沒有正在進行的事務,而基於事務配置需要一個新的事務的時候,Spring 會開啓一個新的由容器管理的事務。

注意,如果你想使用由容器管理的事務,而不想使用 Spring 的事務管理,你就不能配置任何的 Spring 事務管理器。並必須配置 SqlSessionFactoryBean 以使用基本的 MyBatis 的 ManagedTransactionFactory:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="transactionFactory">
    <bean class="org.apache.ibatis.transaction.managed.ManagedTransactionFactory" />
  </property>  
</bean>
@Bean
public SqlSessionFactory sqlSessionFactory() {
  SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
  factoryBean.setDataSource(dataSource());
  factoryBean.setTransactionFactory(new ManagedTransactionFactory());
  return factoryBean.getObject();
}

編程式事務管理

MyBatis 的 SqlSession 提供幾個方法來在代碼中處理事務。但是當使用 MyBatis-Spring 時,你的 bean 將會注入由 Spring 管理的 SqlSession 或映射器。也就是說,Spring 總是爲你處理了事務。

你不能在 Spring 管理的 SqlSession 上調用 SqlSession.commit(),SqlSession.rollback() 或 SqlSession.close() 方法。如果這樣做了,就會拋出 UnsupportedOperationException 異常。在使用注入的映射器時,這些方法也不會暴露出來。

無論 JDBC 連接是否設置爲自動提交,調用 SqlSession 數據方法或在 Spring 事務之外調用任何在映射器中方法,事務都將會自動被提交。

如果你想編程式地控制事務,請參考 the Spring reference document(Data Access -Programmatic transaction management-)。下面的代碼展示瞭如何使用 PlatformTransactionManager 手工管理事務。

TransactionStatus txStatus =
    transactionManager.getTransaction(new DefaultTransactionDefinition());
try {
  userMapper.insertUser(user);
} catch (Exception e) {
  transactionManager.rollback(txStatus);
  throw e;
}
transactionManager.commit(txStatus);

在使用 TransactionTemplate 的時候,可以省略對 commit 和 rollback 方法的調用。

TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.execute(txStatus -> {
  userMapper.insertUser(user);
  return null;
});

注意:雖然這段代碼使用的是一個映射器,但換成 SqlSession 也是可以工作的。

使用 SqlSession

在 MyBatis 中,你可以使用 SqlSessionFactory 來創建 SqlSession。一旦你獲得一個 session 之後,你可以使用它來執行映射了的語句,提交或回滾連接,最後,當不再需要它的時候,你可以關閉 session。使用 MyBatis-Spring 之後,你不再需要直接使用 SqlSessionFactory 了,因爲你的 bean 可以被注入一個線程安全的 SqlSession,它能基於 Spring 的事務配置來自動提交、回滾、關閉 session。

SqlSessionTemplate

SqlSessionTemplate 是 MyBatis-Spring 的核心。作爲 SqlSession 的一個實現,這意味着可以使用它無縫代替你代碼中已經在使用的 SqlSession。SqlSessionTemplate 是線程安全的,可以被多個 DAO 或映射器所共享使用。

當調用 SQL 方法時(包括由 getMapper() 方法返回的映射器中的方法),SqlSessionTemplate 將會保證使用的 SqlSession 與當前 Spring 的事務相關。此外,它管理 session 的生命週期,包含必要的關閉、提交或回滾操作。另外,它也負責將 MyBatis 的異常翻譯成 Spring 中的 DataAccessExceptions。

由於模板可以參與到 Spring 的事務管理中,並且由於其是線程安全的,可以供多個映射器類使用,你應該總是用 SqlSessionTemplate 來替換 MyBatis 默認的 DefaultSqlSession 實現。在同一應用程序中的不同類之間混雜使用可能會引起數據一致性的問題。

可以使用 SqlSessionFactory 作爲構造方法的參數來創建 SqlSessionTemplate 對象。

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
  <constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
@Bean
public SqlSessionTemplate sqlSession() throws Exception {
  return new SqlSessionTemplate(sqlSessionFactory());
}

現在,這個 bean 就可以直接注入到你的 DAO bean 中了。你需要在你的 bean 中添加一個 SqlSession 屬性,就像下面這樣:

public class UserDaoImpl implements UserDao {

  private SqlSession sqlSession;

  public void setSqlSession(SqlSession sqlSession) {
    this.sqlSession = sqlSession;
  }

  public User getUser(String userId) {
    return sqlSession.selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
  }
}

按下面這樣,注入 SqlSessionTemplate:

<bean id="userDao" class="org.mybatis.spring.sample.dao.UserDaoImpl">
  <property name="sqlSession" ref="sqlSession" />
</bean>

SqlSessionTemplate 還有一個接收 ExecutorType 參數的構造方法。這允許你使用如下 Spring 配置來批量創建對象,例如批量創建一些 SqlSession:

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
  <constructor-arg index="0" ref="sqlSessionFactory" />
  <constructor-arg index="1" value="BATCH" />
</bean>
@Bean
public SqlSessionTemplate sqlSession() throws Exception {
  return new SqlSessionTemplate(sqlSessionFactory(), ExecutorType.BATCH);
}

現在所有的映射語句可以進行批量操作了,可以在 DAO 中編寫如下的代碼

public void insertUsers(List<User> users) {
  for (User user : users) {
    sqlSession.insert("org.mybatis.spring.sample.mapper.UserMapper.insertUser", user);
  }
}

注意,只需要在希望語句執行的方法與 SqlSessionTemplate 中的默認設置不同時使用這種配置。

這種配置的弊端在於,當調用這個方法時,不能存在使用不同 ExecutorType 的進行中的事務。要麼確保對不同 ExecutorType 的 SqlSessionTemplate 的調用處在不同的事務中,要麼完全不使用事務。

SqlSessionDaoSupport

SqlSessionDaoSupport 是一個抽象的支持類,用來爲你提供 SqlSession。調用 getSqlSession() 方法你會得到一個 SqlSessionTemplate,之後可以用於執行 SQL 方法,就像下面這樣:

public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
  public User getUser(String userId) {
    return getSqlSession().selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
  }
}

在這個類裏面,通常更傾向於使用 MapperFactoryBean,因爲它不需要額外的代碼。但是,如果你需要在 DAO 中做其它非 MyBatis 的工作或需要一個非抽象的實現類,那麼這個類就很有用了。

SqlSessionDaoSupport 需要通過屬性設置一個 sqlSessionFactory 或 SqlSessionTemplate。如果兩個屬性都被設置了,那麼 SqlSessionFactory 將被忽略。

假設類 UserMapperImpl 是 SqlSessionDaoSupport 的子類,可以編寫如下的 Spring 配置來執行設置:

<bean id="userDao" class="org.mybatis.spring.sample.dao.UserDaoImpl">
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

注入映射器

與其在數據訪問對象(DAO)中手工編寫使用 SqlSessionDaoSupport 或 SqlSessionTemplate 的代碼,還不如讓 Mybatis-Spring 爲你創建一個線程安全的映射器,這樣你就可以直接注入到其它的 bean 中了:

<bean id="fooService" class="org.mybatis.spring.sample.service.FooServiceImpl">
  <constructor-arg ref="userMapper" />
</bean>

注入完畢後,映射器就可以在你的應用邏輯代碼中使用了:

public class FooServiceImpl implements FooService {

  private final UserMapper userMapper;

  public FooServiceImpl(UserMapper userMapper) {
    this.userMapper = userMapper;
  }

  public User doSomeBusinessStuff(String userId) {
    return this.userMapper.getUser(userId);
  }
}

注意代碼中並沒有任何的對 SqlSession 或 MyBatis 的引用。你也不需要擔心創建、打開、關閉 session,MyBatis-Spring 將爲你打理好一切。

註冊映射器

註冊映射器的方法根據你的配置方法,即經典的 XML 配置或新的 3.0 以上版本的 Java 配置(也就是常說的 @Configuration),而有所不同。

XML 配置

在你的 XML 中加入 MapperFactoryBean 以便將映射器註冊到 Spring 中。就像下面一樣:

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
  <property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

如果映射器接口 UserMapper 在相同的類路徑下有對應的 MyBatis XML 映射器配置文件,將會被 MapperFactoryBean 自動解析。不需要在 MyBatis 配置文件中顯式配置映射器,除非映射器配置文件與接口類不在同一個類路徑下。參考 SqlSessionFactoryBean 的 configLocation 屬性以獲取更多信息。

注意 MapperFactoryBean 需要配置一個 SqlSessionFactory 或 SqlSessionTemplate。它們可以分別通過 sqlSessionFactory 和 sqlSessionTemplate 屬性來進行設置。如果兩者都被設置,SqlSessionFactory 將被忽略。由於 SqlSessionTemplate 已經設置了一個 session 工廠,MapperFactoryBean 將使用那個工廠。

Java 配置

@Bean
public MapperFactoryBean<UserMapper> userMapper() throws Exception {
  MapperFactoryBean<UserMapper> factoryBean = new MapperFactoryBean<>(UserMapper.class);
  factoryBean.setSqlSessionFactory(sqlSessionFactory());
  return factoryBean;
}

發現映射器

不需要一個個地註冊你的所有映射器。你可以讓 MyBatis-Spring 對類路徑進行掃描來發現它們。

有幾種辦法來發現映射器:

  • 使用 <mybatis:scan/> 元素
  • 使用 @MapperScan 註解
  • 在經典 Spring XML 配置文件中註冊一個 MapperScannerConfigurer

<mybatis:scan/> 和 @MapperScan 都在 MyBatis-Spring 1.2.0 中被引入。@MapperScan 需要你使用 Spring 3.1+。

<mybatis:scan/>

<mybatis:scan/> 元素會發現映射器,它發現映射器的方法與 Spring 內建的 <context:component-scan/> 發現 bean 的方法非常類似。

下面是一個 XML 配置樣例:

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
  xsi:schemaLocation="
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">

  <mybatis:scan base-package="org.mybatis.spring.sample.mapper" />

  <!-- ... -->

</beans>

base-package 屬性允許你設置映射器接口文件的基礎包。通過使用逗號或分號分隔,你可以設置多個包。並且會在你所指定的包中遞歸搜索映射器。

注意,不需要爲 <mybatis:scan/> 指定 SqlSessionFactory 或 SqlSessionTemplate,這是因爲它將使用能夠被自動注入的 MapperFactoryBean。但如果你正在使用多個數據源(DataSource),自動注入可能不適合你。在這種情況下,你可以使用 factory-ref 或 template-ref 屬性指定你想使用的 bean 名稱。

<mybatis:scan/> 支持基於標記接口或註解的過濾操作。在 annotation 屬性中,可以指定映射器應該具有的特定註解。而在 marker-interface 屬性中,可以指定映射器應該繼承的父接口。當這兩個屬性都被設置的時候,被發現的映射器會滿足這兩個條件。默認情況下,這兩個屬性爲空,因此在基礎包中的所有接口都會被作爲映射器被發現。

被發現的映射器會按照 Spring 對自動發現組件的默認命名策略進行命名(參考 the Spring reference document(Core Technologies -Naming autodetected components-))。也就是說,如果沒有使用註解顯式指定名稱,將會使用映射器的首字母小寫非全限定類名作爲名稱。但如果發現映射器具有 @Component 或 JSR-330 標準中 @Named 註解,會使用註解中的名稱作爲名稱。提醒一下,你可以設置 annotation 屬性爲你自定義的註解,然後在你的註解上設置 org.springframework.stereotype.Component 或 javax.inject.Named(需要使用 Java SE 6 以上)註解,這樣你的註解既可以作爲標記,也可以作爲一個名字提供器來使用了。

提示 <context:component-scan/> 無法發現並註冊映射器。映射器的本質是接口,爲了將它們註冊到 Spring 中,發現器必須知道如何爲找到的每個接口創建一個 MapperFactoryBean。

@MapperScan

當你正在使用 Spring 的基於 Java 的配置時(也就是 @Configuration),相比於使用 <mybatis:scan/>,你會更喜歡用 @MapperScan。

@MapperScan 註解的使用方法如下:

@Configuration
@MapperScan("org.mybatis.spring.sample.mapper")
public class AppConfig {
  // ...
}

這個註解具有與之前見過的 <mybatis:scan/> 元素一樣的工作方式。它也可以通過 markerInterface 和 annotationClass 屬性設置標記接口或註解類。通過配置 sqlSessionFactory 和 sqlSessionTemplate 屬性,你還能指定一個 SqlSessionFactory 或 SqlSessionTemplate。

MapperScannerConfigurer

MapperScannerConfigurer 是一個 BeanDefinitionRegistryPostProcessor,這樣就可以作爲一個 bean,包含在經典的 XML 應用上下文中。爲了配置 MapperScannerConfigurer,使用下面的 Spring 配置:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="basePackage" value="org.mybatis.spring.sample.mapper" />
</bean>

如果你需要指定 sqlSessionFactory 或 sqlSessionTemplate,那你應該要指定的是 bean 名而不是 bean 的引用,因此要使用 value 屬性而不是通常的 ref 屬性:

<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />

提示 在 MyBatis-Spring 1.0.2 之前,sqlSessionFactoryBean 和 sqlSessionTemplateBean 屬性是唯一可用的屬性。但由於 MapperScannerConfigurer 在啓動過程中比 PropertyPlaceholderConfigurer 運行得更早,經常會產生錯誤。基於這個原因,上述的屬性已被廢棄,現在建議使用 sqlSessionFactoryBeanName 和 sqlSessionTemplateBeanName 屬性。

什麼是MyBatis-Spring-Boot-Starter?

MyBatis-Spring-Boot-Starter可幫助您在Spring Boot之上快速構建MyBatis應用程序 。

通過使用此模塊,您將實現:

  • 構建獨立應用程序。
  • 將樣板減少到幾乎爲零。
  • 更少的XML配置。

請求所需

Mybatis-spring-boot-starter需要以下版本:

MyBatis-Spring-Boot-Starter MyBatis-Spring Spring Boot Java
2.0 2.0 or higher 2.0 or higher 8 or higher
1.3 1.3 or higher 1.5 or higher 6 or higher
1.2 1.3 or higher 1.4 or higher 6 or higher
1.1 1.3 or higher 1.3 or higher 6 or higher
1.0 1.2 or higher 1.3 or higher 6 or higher

安裝

使用MyBatis-Spring-Boot-Starter模塊,你只需要包含的文件和它的依賴關係(mybatis-spring-boot-autoconfigure.jar mybatis-spring.jar和mybatis.jar,等…)在類路徑中。

如果你使用Maven只依賴你的pom.xml文件添加下面的:

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.0.1</version>
</dependency>

如果你使用 gradle,在你 build.gradle中添加以下依賴:

dependencies {
  compile("org.mybatis.spring.boot:mybatis-spring-boot-starter:2.0.1")
}

快速設置

正如您可能已經知道的,要在Spring中使用MyBatis,您至少需要一個sqlsessionFactory和一個映射器接口。

MyBatis-Spring-Boot-Starter將:

  • 自動檢測DataSource。
  • 將創建並註冊一個使用sqlsessionFactoryBean將DataSource作爲輸入傳遞的sqlsessionFactory實例。
  • 將創建並註冊從sqlsessionFactory中獲取的sqlsessionTemplate實例。
  • 自動掃描映射器,將它們鏈接到sqlsessiontemplate,並將它們註冊到spring上下文,以便將它們注入bean中。

假設我們有以下映射器:

@Mapper
public interface CityMapper {

  @Select("SELECT * FROM CITY WHERE state = #{state}")
  City findByState(@Param("state") String state);

}

您只需要創建一個普通的Spring boot application,並讓映射器按如下方式注入(在Spring4.3+上提供):

@SpringBootApplication
public class SampleMybatisApplication implements CommandLineRunner {

  private final CityMapper cityMapper;

  public SampleMybatisApplication(CityMapper cityMapper) {
    this.cityMapper = cityMapper;
  }

  public static void main(String[] args) {
    SpringApplication.run(SampleMybatisApplication.class, args);
  }

  @Override
  public void run(String... args) throws Exception {
    System.out.println(this.cityMapper.findByState("CA"));
  }

}

這就是你要做的。您的應用程序現在可以作爲普通的Spring引導應用程序運行。

高級掃描

默認情況下,mybatis Spring引導啓動程序將搜索標記有@mapper註釋的映射器。

您可能需要指定一個自定義註釋或一個用於掃描的標記接口。如果是,則必須使用@mapperscan註釋。更多信息請參見Mybatis Spring參考頁面。

如果MyBatis Spring啓動程序在Spring的上下文中找到至少一個MapperFactoryBean,它將不會啓動掃描過程,因此,如果您想完全停止掃描,應該使用@bean方法顯式註冊映射器。

使用sqlsession

創建了一個SqlSessionTemplate實例並將其添加到Spring上下文中,因此您可以使用mybatis API將其注入beans,如下所示(在Spring4.3+上提供):

@Component
public class CityDao {

  private final SqlSession sqlSession;

  public CityDao(SqlSession sqlSession) {
    this.sqlSession = sqlSession;
  }

  public City selectCityById(long id) {
    return this.sqlSession.selectOne("selectCityById", id);
  }

}

Configuration

與任何其他Spring Boot應用程序一樣,MyBatis-Spring-Boot-Application配置參數存儲在 application.properties(或application.yml)中。

MyBatis使用前綴mybatis作爲其屬性

可用的屬性是:

屬性 描述
config-location MyBatis xml配置文件的位置。
check-config-location 指示是否執行MyBatis xml配置文件的狀態檢查。
mapper-locations Mapper xml配置文件的位置。
type-aliases-package 用於搜索類型別名的包。(包分隔符是“ ,; \ t \ n ”)
type-aliases-super-type 過濾類型別名的超類。如果未指定,則MyBatis將從type-aliases-package中搜索的所有類作爲類型別名處理。
type-handlers-package 用於搜索類型處理程序的包。(包分隔符是“ ,; \ t \ n ”)
executor-type 執行者類型:SIMPLE,REUSE,BATCH。
configuration-properties MyBatis配置的外部化屬性。指定的屬性可以用作MyBatis配置文件和Mapper文件的佔位符。有關詳細信息,請參閱MyBatis參考頁面
configuration 一個MyBatis 配置 bean。關於可用屬性,請參閱MyBatis參考頁面。 注意此屬性不能與config-location同時使用。
例如:
# application.properties
mybatis.type-aliases-package=com.example.domain.model
mybatis.type-handlers-package=com.example.typehandler
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.default-fetch-size=100
mybatis.configuration.default-statement-timeout=30
...
或
# application.yml
mybatis:
    type-aliases-package: com.example.domain.model
    type-handlers-package: com.example.typehandler
    configuration:
        map-underscore-to-camel-case: true
        default-fetch-size: 100
        default-statement-timeout: 30
...

使用配置自定義程序

 

MyBatis-Spring-Boot-Starter提供了使用Java配置文件自定義自動配置生成的MybATIS配置的機會。MyBatis Spring引導啓動程序將自動搜索實現configurationcustomizer接口的bean,並調用自定義MyBatis配置的方法。(自1.2.1或更高版本起提供)

// @Configuration class
@Bean
ConfigurationCustomizer mybatisConfigurationCustomizer() {
  return new ConfigurationCustomizer() {
    @Override
    public void customize(Configuration configuration) {
      // customize ...
    }
  };
}

使用SpringbootVFS

MyBatis-Spring-Boot-Starter提供了SpringBootvfs作爲vfs的實現類。vfs用於從應用程序(或應用程序服務器)中搜索類(例如別名類型的目標類、類型處理程序類)。如果使用可執行JAR運行SpringBoot應用程序,則需要使用SpringBootVFS。mybatis彈簧引導啓動程序提供的自動配置功能自動使用它,但手動配置不會自動使用它(例如,當使用多個數據源時)。

如何在手動配置中使用SpringBootvfs:

// @Configuration class
@Bean
public SqlSessionFactory masterSqlSessionFactory() throws Exception {
  SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
  factoryBean.setDataSource(masterDataSource());
  factoryBean.setVfs(SpringBootVFS.class); // Sets the SpringBootVFS class into SqlSessionFactoryBean
  // ...
  return factoryBean.getObject();
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章