當咱們想在 spring 項目中使用 mybatis 的時候就須要 mybatis-spring 了,它可讓 spring 完美的整合 mybatis 代碼。使用這個類庫中的類,spring 將會加載必要的 mybatis 工廠類和 session 類。 這個類庫也提供一個簡單的方式來注入 mybatis 數據映射器和 SqlSession 到業務層的 bean 中。 並且它也會處理事務, 翻譯 MyBatis 的異常到 Spring 的 DataAccessException 異常(數據訪問異常)中java
咱們先走一個簡單例子,再在基礎上擴展web
使用 mybatis-spring 模塊,須要添加 mybatis-spring-x.x.x.jar
包spring
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.2</version> </dependency>
同時加上 mybatis-x.x.x.jar 包和相關數據庫鏈接包,spring 的依賴添加上 spring-context 和 spring-jdbc,若是是 web 項目,再加上 web 相關的 jar 包便可sql
咱們在使用 mybatis 的時候,最關鍵的是去使用 SqlSession 去執行映射的 SQL 語句。而 SqlSession 是經過 SqlSesionFactory 來獲取的。而 SqlSessionFactory 的實例則是由SqlSessionFactoryBuilder 從 XML 配置文件或一個預先定製的 Configuration 的實例構建出來的數據庫
如今,咱們是要在 spring 上整合 mybatis,須要把 SqlSessionFactory 的建立和 注入交給 spring容器,在 mybatis-spring 中 SqlSessionFactory 的建立交給了 SqlSessionFactoryBean安全
咱們在項目中建立一個 spring 的配置文件,添加相關配置,加上 SqlSessionFactoryBean 的配置
application-mybatis.xmlsession
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 使用註解聲明 --> <context:component-scan base-package="com.brave"/> <!-- 加載屬性資源 --> <context:property-placeholder location="classpath*:conf/*.properties"></context:property-placeholder> <!-- 配置 SqlSessionFactoryBean --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 數據源 --> <property name="dataSource" ref="dataSource" /> <!-- mybatis 配置文件位置(默認配置的話,能夠不用)--> <property name="configLocation" value="classpath:conf/mybatis/mybatis-config.xml"></property> <!-- 配置映射器文件 --> <property name="mapperLocations" value="classpath*:com/brave/dao/mapper/*Mapper.xml" /> </bean> <!-- 配置數據源 --> <!-- 這裏使用的是 druid 鏈接池,須要另外導入 druid.jar --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <!-- 事務管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> </beans>
要注意 SqlSessionFactoryBean 實現了 Spring 的 FactoryBean 接口。 這就說明了由 Spring 最終建立的 bean 不是 SqlSessionFactoryBean 自己。 而是工廠類的 getObject()返回的方法的結果。這種狀況下,Spring 將會在應用啓動時爲你 建立 SqlSessionFactory 對象,而後將它以 SqlSessionFactory 爲名來存儲。在 Java 中, 相同的代碼是:
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
SqlSessionFactory sessionFactory = factoryBean.getObject();
可是通常咱們不直接使用 SqlSessionFactoryBean 或 SqlSessionFactory。由於 session 工廠將會被注入到映射器中 或其它擴展了 SqlSessionDaoSupport 的 DAO(Data Access Object,數據訪問對象)中mybatis
SqlSessionFactory有三個屬性app
mapperLocations 能夠配置多個位置ide
<property name="mapperLocations"> <list> <value>classpath*:conf/mybatis/**/*Mapper.xml</value> <value>classpath*:conf/com/brave/**/*Mapper.xml</value> </list> </property>
在 mybatis 中,咱們使用 SqlSessionFactory 來建立 SqlSession。獲取了一個 session 以後,使用它來執行映射的 SQL 語句、提交或回滾鏈接,最後當再也不須要它的時候關閉 session。
使用 mybatis-spring 以後,就不須要直接使用 SqlSessionFactory 了,由於你的 bean 能夠經過一個線程安全的 SqlSession 來注入,基於 spring 的事務配置來自動提交、回滾、關閉 session。
SqlSessionTemplate 是 mybatis-spring 的核心。它負責管理 mybatis 的 SqlSession, 調用 mybatis 的 SQL 方法、翻譯異常。它是線程安全的,能夠被多個 DAO 所共享使用。
當調用 SQL 方法時,包含從映射器 getMapper()方法返回的方法,SqlSessionTemplate 將會保證使用的 SqlSession 是和當前 Spring 的事務相關的。它管理這 session 的生命週期,包含必要的關閉,提交或回滾操做。
SqlSessionTemplate 對象可使用 SqlSessionFactory 做爲構造方法的參數來建立
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory" /> <!-- 配置了BATCH 表示全部的語句能夠批量操做 --> <constructor-arg index="1" value="BATCH" /> </bean>
SqlSessionTemplate 實現了 SqlSession 接口,不用再代碼中對 mybatis 的 SqlSession 進行替換,直接在 Dao bean中直接注入這個 SqlSession 屬性就能夠了
@Repository public class UpmsUserDaoImpl implements UpmsUserDao { @Autowired private SqlSession sqlSession; @Override public UpmsUser selectOne(Long userId) { return sqlSession.selectOne("com.brave.dao.UpmsUserDao.selectOne", userId); } @Override public List<UpmsUser> selectUser(UpmsUser upmsUser) { return sqlSession.selectList("com.brave.dao.UpmsUserDao.selectUser", upmsUser); } @Override public int insertUser(UpmsUser upmsUser) { return sqlSession.insert("com.brave.dao.UpmsUserDao.insertUser", upmsUser); } }
這裏附上個人映射文件 upmsUserMapper.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.brave.dao.UpmsUserDao"> <resultMap type="com.brave.model.UpmsUser" id="upmsUser"> <id column="user_id" property="userId"/> <result column="loginname" property="loginname"/> <result column="password" property="password"/> <result column="realname" property="realname"/> <result column="phone" property="phone"/> <result column="email" property="email"/> <result column="is_locked" property="locked"/> <result column="gmt_create" property="gmtCreate"/> <result column="gmt_modified" property="gmtModified"/> </resultMap> <select id="selectOne" resultMap="upmsUser"> select * from upms_user where user_id = #{userId} </select> <select id="selectUser" resultMap="upmsUser"> select * from upms_user <where> <if test="loginname != null and loginname != '' "> loginname like #{loginname} </if> <if test="realname != null and realname != '' "> and realname like #{realname} </if> </where> </select> <insert id="insertUser"> insert into upms_user (user_id,loginname,password,realname,is_locked) value(#{userId},#{loginname},#{password},#{realname},#{locked}) </insert> </mapper>
使用 Junit 生成測試類
@RunWith(SpringJUnit4ClassRunner.class) //使用junit4進行測試 @ContextConfiguration ("/conf/spring/applicationContext*.xml") public class UpmsUserDaoImplTest { @Autowired private UpmsUserDao upmsUserDao; @Test public void testSelectOne() { System.out.println(upmsUserDao.selectOne(10001L).toString()); } @Test public void testSelectUser() { UpmsUser user = new UpmsUser(); user.setLoginname("zou"); user.setUserId(2L); List<UpmsUser> upmsUsers = upmsUserDao.selectUser(user); for (UpmsUser upmsUser : upmsUsers) { System.out.println(upmsUser.toString()); } } @Test @Transactional //聲明須要事務 public void testInsertUser() { UpmsUser upmsUser = new UpmsUser(); upmsUser.setUserId(10002L); upmsUser.setLoginname("zou"); upmsUser.setPassword("123456"); upmsUser.setLocked(false); int n = upmsUserDao.insertUser(upmsUser); System.out.println("插入" + n + "行"); } }
SqlSessionDaoSupport 是一個抽象的支持類,用來提供 SqlSession。getSqlSession()方法能夠獲得一個 SqlSessionTemplate
public class UpmsUserDaoImpl2 extends SqlSessionDaoSupport implements UpmsUserDao { @Override public UpmsUser selectOne(Long userId) { return getSqlSession().selectOne("com.brave.dao.UpmsUserDao.selectOne", userId); } }
SqlSessionDaoSupport 須要設置一個 sqlSessionFactory 或 sqlSessionTemplate 屬性
假如是 UpmsUserDaoImpl2 繼承了 SqlSessionDaoSupport:
<bean id="upmsUserDaoImpl" class="com.brave.dao.UpmsUserDaoImpl2"> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean>
能夠建立一個公用的 SuperDao 去繼承 SqlSessionDaoSupport,爲 SuperDao 設置 sqlSessionFactory 屬性,而後讓其餘 dao 去繼承 SuperDao,這樣就不用每一個 dao 都去設置這個屬性了
public class SuperDao extends SqlSessionDaoSupport { @Autowired public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { super.setSqlSessionFactory(sqlSessionFactory); } }
不過一般咱們更經常使用 MapperFactoryBean(只須要接口,不用實現類),由於它不須要額外的代碼。可是若是須要在 DAO 中作其它非 MyBatis 的工做或須要具體的類,那麼這個類就頗有用了。
mybatis-spring 容許 mybatis 參與到 spring 的事務管理中。利用了存在於 Spring 中的 DataSourceTransactionManager,而不是建立一個新的特定的事務管理器
一旦 Spring 的 PlatformTransactionManager 配置好了,能夠在 spring 中以一般的作法來配置事務。@Transactional 註解和 AOP 樣式的配置都是支持的。在事務處理期間,一個單獨的 SqlSession 對象將會被建立和使用。當事務完成時,這個 session 會以合適的方式提交或回滾。
一旦事務建立以後,mybatis-spring 將會透明的管理事務。在你的 DAO 類中就不須要額外的代碼了
要 開 啓 Spring 的 事 務 處 理 , 在 Spring 的 XML 配 置 文 件 中 簡 單 創 建 一 個 DataSourceTransactionManager 對象:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>
在 mybatis 中,咱們能夠建立一個來綁定映射的語句的接口映射器(實際上也就是咱們的 dao 接口),在映射文件的命名空間與咱們的映射器徹底限定名一致,映射語句id名就是映射器的方法名,這樣咱們能夠不用實現這個映射器,經過 sqlSession 獲取映射器,直接使用 sql 方法
UpmsUserDao upmsUserDao = sqlSession.getMapper(UpmsUserDao.class); UpmsUse upmsUse = upmsUserDao.selectOne(10002L);
爲了代替手工使用 SqlSessionDaoSupport 或 SqlSessionTemplate 編寫數據訪問對象 (DAO)的代碼,mybatis-spring 也提供了一個動態代理的實現:MapperFactoryBean。這個類可讓你直接注入 數據映射器接口 到你的 service 層 bean 中。當使用映射器時,直接調用就能夠了,不須要實現 DAO接口,由於 mybatis-spring 將會爲你建立代理。
使用注入的映射器代碼,在 mybatis、spring 或 mybatis-spring 上面不會有直接的依賴。 MapperFactoryBean 建立的代理控制開放和關閉 session,會翻譯任意的異常到 spring 的 DataAccessException 異常中。此外,若是須要或參與到一個已經存在活動事務中,代理將會開啓一個新的 spring 事務。
想要直接使用 數據映射器接口,先添加 MapperFactoryBean 到 spring 中:
<bean id="upmsUserMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="com.brave.mapper.UpmsUserMapper" /> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean>
MapperFactoryBean 建立的代理類實現了 UpmsUserMapper 接口,而且注入到應用程序中。 由於代理建立在運行時環境中,那麼指定的映射器必須是一個接口,而不是一個具體的實現類。
若是 XML 映射器文件在類路徑的位置和映射器類相同時,它會被 MapperFactoryBean 自動解析,不然你須要在 SqlSessionFactoryBean 的 mapperLocations 或是在 mybatis 的配置文件中指明映射文件的位置
這裏附上映射文件,這裏的命名空間必定要是映射器的徹底限定名
<?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.brave.mapper.UpmsUserMapper"> <!-- 這裏的id與映射器的方法一致 --> <select id="selectUser" resultType="com.brave.model.UpmsUser"> select * from upms_user </select> </mapper>
接口映射器 UpmsUserMapper.java
public interface UpmsUserMapper { List<UpmsUser> selectUser(); }
而後咱們在應用程序邏輯中能夠直接使用
@Service public class UpmsUserServiceImpl implements UpmsUserService { @Autowired private UpmsUserMapper upmsUserMapper; @Override public List<UpmsUser> listUser() { return upmsUserMapper.selectUser(); } }
咱們沒有必要在 spring 的 XML 配置文件中註冊全部的映射器。只用使用一個 MapperScannerConfigurer 便可,它會查找類路徑下的映射器並自動將它們建立成 MapperFactoryBean
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.brave.mapper" /> </bean>
這樣就不用每一個 mapper 都配置一個 MapperFactoryBean 了
basePackage 屬性是讓你爲映射器接口文件設置基本的包路徑。 可使用 分號 或 逗號 做爲分隔符設置多於一個的包路徑。每一個映射器將會在指定的包路徑中遞歸地被搜索到
另外還有兩種掃描映射器的方法
<mybatis:scan> 元素將在特定的以逗號分隔的包名列表中搜索映射器 mapper 接口。 要使用這個元素須要添加如下的 schema 聲明
<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="com.brave.mapper" /> </beans>
若是使用基於java的配置,可使用@MapperScan 註解來掃描映射器 Mapper 接口。 @MapperScan 和 <mybatis:scan/> 工做方式 相同,而且也提供了對應的自定義選項
在 spring-boot 項目中可能會使用到
@SpringBootApplication @MapperScan("com.brave.mapper") public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }