mybatis-spring官方中文教程文檔(1.3.1-SNAPSHOT版本)

分類:編程 時間:2016-11-07

簡介

What is MyBatis-Spring?

MyBatis-Spring 會幫助你將 MyBatis 代碼無縫地整合到 Spring 中。 使用這個類庫中的類, Spring 將會加載必要的 MyBatis 工廠類和 session 類。 這個類庫也提供一個簡單的方式來註入 MyBatis 數據映射器和 SqlSession 到業務層的 bean 中。 而且它也會處理事務, 翻譯 MyBatis 的異常到 Spring 的 DataAccessException 異常(數據訪問異常,譯者註)中。最終,它並 不會依賴於 MyBatis,Spring 或 MyBatis-Spring 來構建應用程序代碼。

Motivation

正如第二版那樣,Spring 3.0 也僅支持 iBatis2。那麽,我們就想將 MyBatis3 的支持添加 到 Spring3.0(參考 Spring Jira 中的問題)中。而不幸的是,Spring 3.0 的開發在 MyBatis 3.0 官方發布前就結束了。 因為 Spring 開發團隊不想發布一個基於非發布版的 MyBatis 的整合支 持,那麽 Spring 官方的支持就不得不繼續等待了。要在 Spring 中支持 MyBatis,MyBatis 社 區認為現在應該是自己團結貢獻者和有興趣的人一起來開始將 Spring 的整合作為 MyBatis 社 區的子項目的時候了。

Requirements

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

MyBatis-Spring requires Java 5 or higher and the following MyBatis and Spring versions:

MyBatis-Spring MyBatis Spring 1.0.0 and 1.0.1 3.0.1 to 3.0.5 3.0.0 or higher 1.0.2 3.0.6 3.0.0 or higher 1.1.0 3.1.0 or higher 3.0.0 or higher

Acknowledgements

特別感謝那些使得本項目成為現實的人們(按字母順序排序)。 Eduardo Macarron, Hunter Presnall和Putthibong Boonbong的編碼, 測試和文檔修改工作; Andrius Juozapaitis, Giovanni Cuccu,Raj Nagappan和Tomas Pinos的貢獻;而Simone Tripodi發現了這些人並 把他們帶入項目之中。沒有他們的努力,這個項目是不可能存在的。

 

第二章 入門

 

本章將會以簡略的步驟告訴你如何安裝和創建 MyBatis-Spring,並構建一個簡單的數據 訪問事務性的應用程序。

Installation

要使用 MyBatis-Spring 模塊,你只需要包含 mybatis-spring-x.x.x.jar 文 件就可以了,並在類路徑中加入相關的依賴。

如果你使用 Maven,那麽在 pom.xml 中加入下面的代碼即可:


  org.mybatis
  mybatis-spring
  x.x.x

Quick Setup

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

在 MyBatis-Spring 中,SqlSessionFactoryBean 是用於創建 SqlSessionFactory 的。要 配置這個工廠 bean,放置下面的代碼在 Spring 的 XML 配置文件中:


  

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

Assume you have a data mapper class defined like the following:

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

那麽可以使用 MapperFactoryBean,像下面這樣來把接口加入到 Spring 中:


  
  

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

一旦配置好,你可以用註入其它任意 Spring 的 bean 相同的方式直接註入映射器到你的 business/service 對象中。MapperFactoryBean 處理 SqlSession 的創建和關閉它。如果使用 了 Spring 的事務,那麽當事務完成時,session 將會提交或回滾。最終,任何異常都會被翻 譯成 Spring 的 DataAccessException 異常。

調用 MyBatis 數據方法現在只需一行代碼:

public class FooServiceImpl implements FooService {

private UserMapper userMapper;

public void setUserMapper(UserMapper userMapper) {
  this.userMapper = userMapper;
}

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

SqlSessionFactoryBean

在基本的 MyBatis 中,session 工廠可以使用 SqlSessionFactoryBuilder 來創建。而在 MyBatis-Spring 中,則使用 SqlSessionFactoryBean 來替代。

Setup

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


  

要註意 SqlSessionFactoryBean 實現了 Spring 的 FactoryBean 接口(請參考 Spring 文 檔的 3.8 章節)這就說明了由 Spring 最終創建的 bean 不是 SqlSessionFactoryBean 本身, 。 而是工廠類的 getObject()返回的方法的結果。這種情況下,Spring 將會在應用啟動時為你 創建 SqlSessionFactory 對象,然後將它以 SqlSessionFactory 為名來存儲。在 Java 中, 相同的代碼是:

SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
SqlSessionFactory sessionFactory = factoryBean.getObject();

在一般的 MyBatis-Spring 用法中, 你不需要直接使用 SqlSessionFactoryBean 或和其對 應的 SqlSessionFactory。相反,session 工廠將會被註入到 MapperFactoryBean 或其它擴 展了 SqlSessionDaoSupport 的 DAO(Data Access Object,數據訪問對象,譯者註)中。

屬性

SqlSessionFactory 有一個單獨的必須屬性,就是 JDBC 的 DataSource。這可以是任意 的 DataSource,其配置應該和其它 Spring 數據庫連接是一樣的。

一個通用的屬性是 configLocation,它是用來指定 MyBatis 的 XML 配置文件路徑的。 如果基本的 MyBatis 配置需要改變, 那麽這就是一個需要它的地方。 通常這會是 或的部分。

要註意這個配置文件不需要是一個完整的 MyBatis 配置。確切地說,任意環境,數據源 和 MyBatis 的事務管理器都會被忽略。SqlSessionFactoryBean 會創建它自己的,使用這些 值定制 MyBatis 的 Environment 時是需要的。

如果 MyBatis 映射器 XML 文件在和映射器類相同的路徑下不存在,那麽另外一個需要 配置文件的原因就是它了。使用這個配置,有兩種選擇。第一是手動在 MyBatis 的 XML 配 置文件中使用部分來指定類路徑。第二是使用工廠 bean 的 mapperLocations 屬 性。

mapperLocations 屬性使用一個資源位置的 list。 這個屬性可以用來指定 MyBatis 的 XML 映射器文件的位置。 它的值可以包含 Ant 樣式來加載一個目錄中所有文件, 或者從基路徑下 遞歸搜索所有路徑。比如:


  
  

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

在容器環境管理事務中,一個可能需要的屬性是 transactionFactoryClass。請參考 第四章(4.2 節)中來查看有關部分。

NOTE Since 1.3.0, configuration property has been added. It can be specified a Configuration instance directly without MyBatis XML configuration file. For example:


  
  
    
      
    
  

第四章 事務

一個使用 MyBatis-Spring 的主要原因是它允許 MyBatis 參與到 Spring 的事務管理中。而 不是給 MyBatis 創建一個新的特定的事務管理器,MyBatis-Spring 利用了存在於 Spring 中的 DataSourceTransactionManager。

一旦 Spring 的 PlatformTransactionManager 配置好了,你可以在 Spring 中以你通常的做 法來配置事務。@Transactional 註解和 AOP(Aspect-Oriented Program,面向切面編程,譯 者註)樣式的配置都是支持的。在事務處理期間,一個單獨的 SqlSession 對象將會被創建 和使用。當事務完成時,這個 session 會以合適的方式提交或回滾。

一旦事務創建之後,MyBatis-Spring 將會透明的管理事務。在你的 DAO 類中就不需要額 外的代碼了。

標準配置

要 開 啟 Spring 的 事 務 處 理 , 在 Spring 的 XML 配 置 文 件 中 簡 單 創 建 一 個 DataSourceTransactionManager 對象:


  

指定的 DataSource 一般可以是你使用 Spring 的任意 JDBC DataSource。這包含了連接 池和通過 JNDI 查找獲得的 DataSource。

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

容器管理事務

如果你正使用一個 JEE 容器而且想讓 Spring 參與到容器管理事務(Container managed transactions,CMT,譯者註)中,那麽 Spring 應該使用 JtaTransactionManager 或它的容 器指定的子類來配置。做這件事情的最方便的方式是用 Spring 的事務命名空間:


在這種配置中,MyBatis 將會和其它由 CMT 配置的 Spring 事務資源一樣。Spring 會自動 使用任意存在的容器事務,在上面附加一個 SqlSession。如果沒有開始事務,或者需要基 於事務配置,Spring 會開啟一個新的容器管理事務。

註 意 , 如 果 你 想 使 用 CMT , 而 不 想 使 用 Spring 的 事 務 管 理 , 你 就 必 須 配 置 SqlSessionFactoryBean 來使用基本的 MyBatis 的 ManagedTransactionFactory 而不是其 它任意的 Spring 事務管理器:


  
  
    
    

編程式事務管理

MyBatis 的 SqlSession 提供指定的方法來處理編程式的事務。 但是當使用 MyBatis-Spring 時, bean 將會使用 Spring 管理的 SqlSession 或映射器來註入。 那就是說 Spring 通常是處理 事務的。

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

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

如果你想編程式地控制事務,請參考 Spring 手冊的 10.6 節。這段代碼展示了如何手動 使用在 10.6.2 章節描述的 PlatformTransactionManager 來處理事務。

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

TransactionStatus status = txManager.getTransaction(def);
try {
  userMapper.insertUser(user);
}
catch (MyException ex) {
  txManager.rollback(status);
  throw ex;
}
txManager.commit(status);

註意這段代碼展示了一個映射器,但它也能和 SqlSession 一起使用。

第五章 使用 SqlSession

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

註意通常不必直接使用 SqlSession。 在大多數情況下 MapperFactoryBean, 將會在 bean 中註入所需要的映射器。下一章節中的 MapperFactoryBean(6.1 節)會解釋這個細節。

SqlSessionTemplate

SqlSessionTemplate 是 MyBatis-Spring 的核心。 這個類負責管理 MyBatis 的 SqlSession, 調用 MyBatis 的 SQL 方法, 翻譯異常。 SqlSessionTemplate 是線程安全的, 可以被多個 DAO 所共享使用。

當調用 SQL 方法時, 包含從映射器 getMapper()方法返回的方法, SqlSessionTemplate 將會保證使用的 SqlSession 是和當前 Spring 的事務相關的。此外,它管理 session 的生命 周期,包含必要的關閉,提交或回滾操作。

SqlSessionTemplate 實現了 SqlSession 接口,這就是說,在代碼中無需對 MyBatis 的 SqlSession 進行替換。 SqlSessionTemplate 通常是被用來替代默認的 MyBatis 實現的 DefaultSqlSession , 因為模板可以參與到 Spring 的事務中並且被多個註入的映射器類所使 用時也是線程安全的。相同應用程序中兩個類之間的轉換可能會引起數據一致性的問題。

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 (User) sqlSession.selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
  }
}

如下註入 SqlSessionTemplate:


  

SqlSessionTemplate 有一個使用 ExecutorType 作為參數的構造方法。這允許你用來 創建對象,比如,一個批量 SqlSession,但是使用了下列 Spring 配置的 XML 文件:


  
  

現在你所有的語句可以批量操作了,下面的語句就可以在 DAO 中使用了。

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

註意,如果所需的執行方法和默認的 SqlSessionFactory 設置不同,這種配置風格才 能使用。

對這種形式需要說明的是當這個方法被調用時,不能有一個存在使用不同 ExecutorType 運行的事務。也要保證在不同的事務中,使用不同執行器來調用 SqlSessionTemplate 時, (比如 PROPAGATION_REQUIRES_NEW)或完全在一個事務外面。

SqlSessionDaoSupport

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

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

通常 MapperFactoryBean 是這個類的首選,因為它不需要額外的代碼。但是,如果你 需要在 DAO 中做其它非 MyBatis 的工作或需要具體的類,那麽這個類就很有用了。

SqlSessionDaoSupport 需要一個 sqlSessionFactory 或 sqlSessionTemplate 屬性來 設 置 。 這 些 被 明 確 地 設 置 或 由 Spring 來 自 動 裝 配 。 如 果 兩 者 都 被 設 置 了 , 那 麽 SqlSessionFactory 是被忽略的。

假設類 UserMapperImpl 是 SqlSessionDaoSupport 的子類,它可以在 Spring 中進行如 下的配置:


  

第六章 註入映射器

為了代替手工使用 SqlSessionDaoSupport 或 SqlSessionTemplate 編寫數據訪問對象 (DAO)的代碼,MyBatis-Spring 提供了一個動態代理的實現:MapperFactoryBean。這個類 可以讓你直接註入數據映射器接口到你的 service 層 bean 中。當使用映射器時,你僅僅如調 用你的 DAO 一樣調用它們就可以了,但是你不需要編寫任何 DAO 實現的代碼,因為 MyBatis-Spring 將會為你創建代理。

使用註入的映射器代碼,在 MyBatis,Spring 或 MyBatis-Spring 上面不會有直接的依賴。 MapperFactoryBean 創建的代理控制開放和關閉 session,翻譯任意的異常到 Spring 的 DataAccessException 異常中。此外,如果需要或參與到一個已經存在活動事務中,代理將 會開啟一個新的 Spring 事務。

MapperFactoryBean

數據映射器接口可以按照如下做法加入到 Spring 中:


  
  

MapperFactoryBean 創建的代理類實現了 UserMapper 接口,並且註入到應用程序中。 因為代理創建在運行時環境中(Runtime,譯者註) ,那麽指定的映射器必須是一個接口,而 不是一個具體的實現類。

如果 UserMapper 有一個對應的 MyBatis 的 XML 映射器文件, 如果 XML 文件在類路徑的 位置和映射器類相同時, 它會被 MapperFactoryBean 自動解析。 沒有必要在 MyBatis 配置文 件 中 去 指 定 映 射 器 , 除 非 映 射 器 的 XML 文 件 在 不 同 的 類 路 徑 下 。 可 以 參 考 SqlSessionFactoryBean 的 configLocation 屬性(第三章)來獲取更多信息。

註意,當 MapperFactoryBean 需要 SqlSessionFactory 或 SqlSessionTemplate 時。 這些可以通過各自的 SqlSessionFactory 或 SqlSessionTemplate 屬性來設置, 或者可以由 Spring 來自動裝配。如果兩個屬性都設置了,那麽 SqlSessionFactory 就會被忽略,因為 SqlSessionTemplate 是需要有一個 session 工廠的設置; 那個工廠會由 MapperFactoryBean. 來使用。

你可以直接在 business/service 對象中以和註入任意 Spring bean 的相同方式直接註入映 射器:


  

這個 bean 可以直接在應用程序邏輯中使用:

public class FooServiceImpl implements FooService {

  private UserMapper userMapper;

  public void setUserMapper(UserMapper userMapper) {
    this.userMapper = userMapper;
  }

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

註意在這段代碼中沒有 SqlSession 或 MyBatis 的引用。也沒有任何需要創建,打開或 關閉 session 的代碼,MyBatis-Spring 會來關心它的。

MapperScannerConfigurer

沒有必要在 Spring 的 XML 配置文件中註冊所有的映射器。相反,你可以使用一個 MapperScannerConfigurer , 它 將 會 查 找 類 路 徑 下 的 映 射 器 並 自 動 將 它 們 創 建 成 MapperFactoryBean。

要創建 MapperScannerConfigurer,可以在 Spring 的配置中添加如下代碼:


  

basepackage 屬性是讓你為映射器接口文件設置基本的包路徑。 你可以使用分號或逗號 作為分隔符設置多於一個的包路徑。每個映射器將會在指定的包路徑中遞歸地被搜索到。

MapperScannerConfigurer 屬性不支持使用了 PropertyPlaceholderConfigurer 的屬 性替換,因為會在 Spring 其中之前來它加載。但是,你可以使用 PropertiesFactoryBean 和 SpEL 表達式來作為替代。

註 意 , 沒 有 必 要 去 指 定 SqlSessionFactory 或 SqlSessionTemplate , 因 為 MapperScannerConfigurer 將會創建 MapperFactoryBean,之後自動裝配。但是,如果你使 用了一個 以上的 DataSource ,那 麽自動 裝配可 能會失效 。這種 情況下 ,你可 以使用 sqlSessionFactoryBeanName 或 sqlSessionTemplateBeanName 屬性來設置正確的 bean 名 稱來使用。這就是它如何來配置的,註意 bean 的名稱是必須的,而不是 bean 的引用,因 此,value 屬性在這裏替代通常的 ref:

MapperScannerConfigurer 支 持 過 濾 由 指 定 的 創 建 接 口 或 註 解 創 建 映 射 器 。 annotationClass 屬性指定了要尋找的註解名稱。 markerInterface 屬性指定了要尋找的父 接口。如果兩者都被指定了,加入到接口中的映射器會匹配兩種標準。默認情況下,這兩個 屬性都是 null,所以在基包中給定的所有接口可以作為映射器加載。

被發現的映射器將會使用 Spring 對自動偵測組件(參考 Spring 手冊的 3.14.4)默認的命 名策略來命名。也就是說,如果沒有發現註解,它就會使用映射器的非大寫的非完全限定類 名。但是如果發現了@Component 或 JSR-330 的@Named 註解,它會獲取名稱。註意你可以 配 置 到 org.springframework.stereotype.Component , javax.inject.Named(如果你使用 JSE 6 的話)或你自己的註解(肯定是自我註解)中,這 樣註解將會用作生成器和名稱提供器。

第七章 使用 MyBatis API

使用 MyBatis-Spring,你可以繼續直接使用 MyBatis 的 API。僅僅在代碼中使用 Spring 中 的 SqlSessionFactoryBean 來創建一個 SqlSessionFactory。

public class UserMapperSqlSessionImpl implements UserMapper {
  // SqlSessionFactory would normally be set by SqlSessionDaoSupport
  private SqlSessionFactory sqlSessionFactory;

  public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
    this.sqlSessionFactory = sqlSessionFactory;
  }

  public User getUser(String userId) {
    // note standard MyBatis API usage - opening and closing the session manually
    SqlSession session = sqlSessionFactory.openSession();

    try {
      return (User) session.selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
    } finally {
      session.close();
    }
  }
}

小心使用此選項, 因為錯誤的使用會產生運行時錯誤, 或者更糟糕的數據一致性的問題。 這些是告誡:

  • 它不會參與到 Spring 的事務之中。

  • 如果 SqlSession 使用 DataSource,它也會被 Spring 事務管理器使用,而且當前 有事務在進行時,這段代碼會拋出異常。

  • MyBatis 的 DefaultSqlSession 是線程不安全的。如果在 bean 中註入了它,就會 發生錯誤。

  • 使用 DefaultSqlSession 創建的映射器也不是線程安全的。如果你將它們註入到 bean 中,是會發生錯誤的。

  • 你必須保證在 finally 塊中來關閉 SqlSession。

    Sample Code

    NOTE See JPetstore 6 demo to know about how to use Spring with a full web application server. .

    You can check out sample code from the MyBatis-Spring repo:

    Any of the samples can be run with JUnit 4.

    The sample code shows a typical design where a transactional service gets domain objects from a data access layer.

    FooService.java acts as the service:

    @Transactional
    public class FooService {
    
      private UserMapper userMapper;
    
      public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
      }
    
      public User doSomeBusinessStuff(String userId) {
        return this.userMapper.getUser(userId);
      }
    
    }

    It is a transactional bean, so a transaction is started when any of its methods is called and committed when the method ends without throwing an unchecked exception. Notice that transactional behaviour is configured with the @Transactional attribute. This is not required; any other way provided by Spring can be used to demarcate your transactions.

    This service calls a data access layer built with MyBatis. This layer consists on a just an interface UserMapper.java that will be used with a dynamic proxy built by MyBatis at runtime and injected into the service by Spring.

    public interface UserMapper {
    
      User getUser(String userId);
    
    }

    Note that, for the sake of simplicity we used the interface UserMapper.java for the DAO scenario where a DAO is built with an interface and a implementation though in this case it would have been more adequate to use an interface called UserDao.java instead.

    We will see different ways to find the mapper interface, register it to Spring and inject it into the service bean:

    Scenarios Sample test Description SampleMapperTest.java Shows you the base configuration based on a MapperFactoryBean that will dynamically build an implementation forUserMapper SampleScannerTest.java Shows how to use the MapperScannerConfigurer so all the mappers in a project are autodiscovered. SampleSqlSessionTest.java Shows how to hand code a DAO using a Spring managed SqlSession and providing your own implementationUserDaoImpl.java. SampleConfigurationTest.java Shows how to use Spring's @Configuration to create MyBatis beans manually. SampleEnableTest Shows how to use Spring's @Configuration with the @MapperScann annotation so mappers are autodiscovered. SampleNamespaceTest Shows how to use the custom MyBatis XML namespace.

    Please take a look at the different applicationContext.xml files to see MyBatis-Spring in action.


Tags: following 應用程序 higher 中文 Java

文章來源:


ads
ads

相關文章
ads

相關文章

ad