Spring + mybatis 整合

來源:http://haohaoxuexi.iteye.com/blog/1843309

Mybatis整合Spring

       根據官方的說法,在ibatis3,也就是Mybatis3問世之前,Spring3的開發工作就已經完成了,所以Spring3中還是沒有對Mybatis3的支持。因此由Mybatis社區自己開發了一個Mybatis-Spring用來滿足Mybatis用戶整合Spring的需求。下面就將通過Mybatis-Spring來整合Mybatis跟Spring的用法做一個簡單的介紹。

MapperFactoryBean

       首先,我們需要從Mybatis官網上下載Mybatis-Spring的jar包添加到我們項目的類路徑下,當然也需要添加Mybatis的相關jar包和Spring的相關jar包。我們知道在Mybatis的所有操作都是基於一個SqlSession的,而SqlSession是由SqlSessionFactory來產生的,SqlSessionFactory又是由SqlSessionFactoryBuilder來生成的。但是Mybatis-Spring是基於SqlSessionFactoryBean的。在使用Mybatis-Spring的時候,我們也需要SqlSession,而且這個SqlSession是內嵌在程序中的,一般不需要我們直接訪問。SqlSession也是由SqlSessionFactory來產生的,但是Mybatis-Spring給我們封裝了一個SqlSessionFactoryBean,在這個bean裏面還是通過SqlSessionFactoryBuilder來建立對應的SqlSessionFactory,進而獲取到對應的SqlSession。通過SqlSessionFactoryBean我們可以通過對其指定一些屬性來提供Mybatis的一些配置信息。所以接下來我們需要在Spring的applicationContext配置文件中定義一個SqlSessionFactoryBean。

 

Xml代碼  收藏代碼
  1. <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
  2.        <property name="dataSource" ref="dataSource" />  
  3.        <property name="mapperLocations"  
  4.               value="classpath:com/tiantian/ckeditor/mybatis/mappers/*Mapper.xml" />  
  5.        <property name="typeAliasesPackage" value="com.tiantian.ckeditor.model" />  
  6. </bean>  
 

       在定義SqlSessionFactoryBean的時候,dataSource屬性是必須指定的,它表示用於連接數據庫的數據源。當然,我們也可以指定一些其他的屬性,下面簡單列舉幾個:

  •  mapperLocations:它表示我們的Mapper文件存放的位置,當我們的Mapper文件跟對應的Mapper接口處於同一位置的時候可以不用指定該屬性的值。
  • configLocation:用於指定Mybatis的配置文件位置。如果指定了該屬性,那麼會以該配置文件的內容作爲配置信息構建對應的SqlSessionFactoryBuilder,但是後續屬性指定的內容會覆蓋該配置文件裏面指定的對應內容。
  •  typeAliasesPackage:它一般對應我們的實體類所在的包,這個時候會自動取對應包中不包括包名的簡單類名作爲包括包名的別名。多個package之間可以用逗號或者分號等來進行分隔。
  •  typeAliases:數組類型,用來指定別名的。指定了這個屬性後,Mybatis會把這個類型的短名稱作爲這個類型的別名,前提是該類上沒有標註@Alias註解,否則將使用該註解對應的值作爲此種類型的別名。
Xml代碼  收藏代碼
  1. <property name="typeAliases">  
  2.     <array>  
  3.         <value>com.tiantian.mybatis.model.Blog</value>  
  4.         <value>com.tiantian.mybatis.model.Comment</value>  
  5.     </array>  
  6. </property>  
 
  •  plugins:數組類型,用來指定Mybatis的Interceptor。
  •  typeHandlersPackage:用來指定TypeHandler所在的包,如果指定了該屬性,SqlSessionFactoryBean會自動把該包下面的類註冊爲對應的TypeHandler。多個package之間可以用逗號或者分號等來進行分隔。
  •  typeHandlers:數組類型,表示TypeHandler。

        接下來就是在Spring的applicationContext文件中定義我們想要的Mapper對象對應的MapperFactoryBean了。通過MapperFactoryBean可以獲取到我們想要的Mapper對象。MapperFactoryBean實現了Spring的FactoryBean接口,所以MapperFactoryBean是通過FactoryBean接口中定義的getObject方法來獲取對應的Mapper對象的。在定義一個MapperFactoryBean的時候有兩個屬性需要我們注入,一個是Mybatis-Spring用來生成實現了SqlSession接口的SqlSessionTemplate對象的sqlSessionFactory;另一個就是我們所要返回的對應的Mapper接口了。

       定義好相應Mapper接口對應的MapperFactoryBean之後,我們就可以把我們對應的Mapper接口注入到由Spring管理的bean對象中了,比如Service bean對象。這樣當我們需要使用到相應的Mapper接口時,MapperFactoryBean會從它的getObject方法中獲取對應的Mapper接口,而getObject內部還是通過我們注入的屬性調用SqlSession接口的getMapper(Mapper接口)方法來返回對應的Mapper接口的。這樣就通過把SqlSessionFactory和相應的Mapper接口交給Spring管理實現了Mybatis跟Spring的整合。

Spring的applicationContext.xml配置文件:

 

Xml代碼  收藏代碼
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
  4.     xmlns:mvc="http://www.springframework.org/schema/mvc"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  7.      http://www.springframework.org/schema/context  
  8.    http://www.springframework.org/schema/context/spring-context-3.0.xsd  
  9.      http://www.springframework.org/schema/mvc  
  10.      http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">  
  11.     <context:component-scan base-package="com.tiantian.mybatis"/>  
  12.     <context:property-placeholder location="classpath:config/jdbc.properties"/>  
  13.     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"  
  14.        destroy-method="close">  
  15.        <property name="driverClassName" value="${jdbc.driver}" />  
  16.        <property name="url" value="${jdbc.url}" />  
  17.        <property name="username" value="${jdbc.username}" />  
  18.        <property name="password" value="${jdbc.password}" />  
  19.     </bean>  
  20.    
  21.     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
  22.        <property name="dataSource" ref="dataSource" />  
  23.        <property name="mapperLocations" value="classpath:com/tiantian/mybatis/mapper/*.xml"/>  
  24.        <property name="typeAliasesPackage" value="com.tiantian.mybatis.model" />  
  25.     </bean>  
  26.    
  27.     <bean id="blogMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">  
  28.        <property name="mapperInterface"  
  29.            value="com.tiantian.mybatis.mapper.BlogMapper" />  
  30.        <property name="sqlSessionFactory" ref="sqlSessionFactory" />  
  31.     </bean>  
  32.    
  33. </beans>  
 

BlogMapper.xml文件

 

Xml代碼  收藏代碼
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE mapper  
  3.   PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
  4.   "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
  5. <mapper namespace="com.tiantian.mybatis.mapper.BlogMapper">  
  6. <!--  新增記錄  -->  
  7.     <insert id="insertBlog" parameterType="Blog" useGeneratedKeys="true" keyProperty="id">  
  8.         insert into t_blog(title,content,owner) values(#{title},#{content},#{owner})  
  9.     </insert>  
  10. <!--  查詢單條記錄  -->  
  11.     <select id="selectBlog" parameterType="int" resultMap="BlogResult">  
  12.        select * from t_blog where id = #{id}  
  13.     </select>  
  14. <!--  修改記錄  -->  
  15.     <update id="updateBlog" parameterType="Blog">  
  16.         update t_blog set title = #{title},content = #{content},owner = #{owner} where id = #{id}  
  17.     </update>  
  18. <!--  查詢所有記錄  -->  
  19.     <select id="selectAll" resultType="Blog">  
  20.         select * from t_blog  
  21.     </select>  
  22. <!--  刪除記錄  -->  
  23.     <delete id="deleteBlog" parameterType="int">  
  24.        delete from t_blog where id = #{id}  
  25.     </delete>  
  26.      
  27. </mapper>  
 

BlogMapper.java:

 

Java代碼  收藏代碼
  1. package com.tiantian.mybatis.mapper;  
  2.    
  3. import java.util.List;  
  4. import com.tiantian.mybatis.model.Blog;  
  5.    
  6. publicinterface BlogMapper {  
  7.    
  8.     public Blog selectBlog(int id);  
  9.      
  10.     publicvoid insertBlog(Blog blog);  
  11.      
  12.     publicvoid updateBlog(Blog blog);  
  13.      
  14.     publicvoid deleteBlog(int id);  
  15.      
  16.     public List<Blog> selectAll();  
  17.      
  18. }  
 

BlogServiceImpl.java:

 

Java代碼  收藏代碼
  1. package com.tiantian.mybatis.service.impl;  
  2.    
  3. import java.util.List;  
  4. import javax.annotation.Resource;  
  5. import org.springframework.stereotype.Service;  
  6. import com.tiantian.mybatis.mapper.BlogMapper;  
  7. import com.tiantian.mybatis.model.Blog;  
  8. import com.tiantian.mybatis.service.BlogService;  
  9.    
  10. @Service  
  11. publicclass BlogServiceImpl implements BlogService {  
  12.    
  13.     private BlogMapper blogMapper;  
  14.      
  15.     publicvoid deleteBlog(int id) {  
  16.        blogMapper.deleteBlog(id);  
  17.     }  
  18.    
  19.     public Blog find(int id) {  
  20.        returnblogMapper.selectBlog(id);  
  21.     }  
  22.    
  23.     public List<Blog> find() {  
  24.        returnblogMapper.selectAll();  
  25.     }  
  26.    
  27.     publicvoid insertBlog(Blog blog) {  
  28.        blogMapper.insertBlog(blog);  
  29.     }  
  30.    
  31.     publicvoid updateBlog(Blog blog) {  
  32.        blogMapper.updateBlog(blog);  
  33.     }  
  34.    
  35.     public BlogMapper getBlogMapper() {  
  36.        returnblogMapper;  
  37.     }  
  38.    
  39.     @Resource  
  40.     publicvoid setBlogMapper(BlogMapper blogMapper) {  
  41.        this.blogMapper = blogMapper;  
  42.     }  
  43.    
  44. }  
上訴方法配置好後,配置xml applicationContext.xml中 blogMapper 直接和作爲bean,用接口BlogMapper來聲明就可以用了,*Mapper.xml中的方法和接口

中的方法是一一對應的,並且xml中的域名稱一定配上,路徑和接口的路徑包一定一樣,否則會導致找不到mapper


MapperScannerConfigurer

       利用上面的方法進行整合的時候,我們有一個Mapper就需要定義一個對應的MapperFactoryBean,當我們的Mapper比較少的時候,這樣做也還可以,但是當我們的Mapper相當多時我們再這樣定義一個個Mapper對應的MapperFactoryBean就顯得速度比較慢了。爲此Mybatis-Spring爲我們提供了一個叫做MapperScannerConfigurer的類,通過這個類Mybatis-Spring會自動爲我們註冊Mapper對應的MapperFactoryBean對象。

       如果我們需要使用MapperScannerConfigurer來幫我們自動掃描和註冊Mapper接口的話我們需要在Spring的applicationContext配置文件中定義一個MapperScannerConfigurer對應的bean。對於MapperScannerConfigurer而言有一個屬性是我們必須指定的,那就是basePackage。basePackage是用來指定Mapper接口文件所在的基包的,在這個基包或其所有子包下面的Mapper接口都將被搜索到。多個基包之間可以使用逗號或者分號進行分隔。最簡單的MapperScannerConfigurer定義就是隻指定一個basePackage屬性,如:

 

Xml代碼  收藏代碼
  1. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
  2.    <property name="basePackage" value="com.tiantian.mybatis.mapper" />  
  3. </bean>  
 

       這樣MapperScannerConfigurer就會掃描指定基包下面的所有接口,並把它們註冊爲一個個MapperFactoryBean對象。當使用MapperScannerConfigurer加basePackage屬性的時候,我們上面例子的applicationContext配置文件將變爲這樣:

 

Xml代碼  收藏代碼
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
  4.     xmlns:mvc="http://www.springframework.org/schema/mvc"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  7.      http://www.springframework.org/schema/context  
  8.      http://www.springframework.org/schema/context/spring-context-3.0.xsd  
  9.      http://www.springframework.org/schema/mvc  
  10.      http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">  
  11.    
  12.     <context:component-scan base-package="com.tiantian.mybatis" />  
  13.     <context:property-placeholder location="classpath:config/jdbc.properties" />  
  14.     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"  
  15.        destroy-method="close">  
  16.        <property name="driverClassName" value="${jdbc.driver}" />  
  17.        <property name="url" value="${jdbc.url}" />  
  18.        <property name="username" value="${jdbc.username}" />  
  19.        <property name="password" value="${jdbc.password}" />  
  20.     </bean>  
  21.     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
  22.        <property name="dataSource" ref="dataSource" />  
  23.        <property name="mapperLocations" value="classpath:com/tiantian/mybatis/mapper/*.xml" />  
  24.        <property name="typeAliasesPackage" value="com.tiantian.mybatis.model" />  
  25.     </bean>  
  26.     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
  27.        <property name="basePackage" value="com.tiantian.mybatis.mapper" />  
  28.     </bean>  
  29. </beans>  

 

有時候我們指定的基包下面的並不全是我們定義的Mapper接口,爲此MapperScannerConfigurer還爲我們提供了另外兩個可以縮小搜索和註冊範圍的屬性。一個是annotationClass,另一個是markerInterface。

  • annotationClass:當指定了annotationClass的時候,MapperScannerConfigurer將只註冊使用了annotationClass註解標記的接口。
  • markerInterface:markerInterface是用於指定一個接口的,當指定了markerInterface之後,MapperScannerConfigurer將只註冊繼承自markerInterface的接口。

       如果上述兩個屬性都指定了的話,那麼MapperScannerConfigurer將取它們的並集,而不是交集。即使用了annotationClass進行標記或者繼承自markerInterface的接口都將被註冊爲一個MapperFactoryBean。

現在假設我們的Mapper接口都繼承了一個SuperMapper接口,那麼我們就可以這樣來定義我們的MapperScannerConfigurer。

 

Xml代碼  收藏代碼
  1. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
  2.    <property name="basePackage" value="com.tiantian.mybatis.mapper" />  
  3.    <property name="markerInterface" value="com.tiantian.mybatis.mapper.SuperMapper"/>  
  4. </bean>  
 

 

       如果是都使用了註解MybatisMapper標記的話,那麼我們就可以這樣來定義我們的MapperScannerConfigurer。

 

Xml代碼  收藏代碼
  1. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
  2.    <property name="basePackage" value="com.tiantian.mybatis.mapper" />  
  3.    <property name="annotationClass" value="com.tiantian.mybatis.annotation.MybatisMapper"/>  
  4. </bean>   


       除了用於縮小注冊Mapper接口範圍的屬性之外,我們還可以指定一些其他屬性,如:

  •  sqlSessionFactory:這個屬性已經廢棄。當我們使用了多個數據源的時候我們就需要通過sqlSessionFactory來指定在註冊MapperFactoryBean的時候需要使用的SqlSessionFactory,因爲在沒有指定sqlSessionFactory的時候,會以Autowired的方式自動注入一個。換言之當我們只使用一個數據源的時候,即只定義了一個SqlSessionFactory的時候我們就可以不給MapperScannerConfigurer指定SqlSessionFactory。
  • sqlSessionFactoryBeanName:它的功能跟sqlSessionFactory是一樣的,只是它指定的是定義好的SqlSessionFactory對應的bean名稱。
  • sqlSessionTemplate:這個屬性已經廢棄。它的功能也是相當於sqlSessionFactory的,因爲就像前面說的那樣,MapperFactoryBean最終還是使用的SqlSession的getMapper方法取的對應的Mapper對象。當定義有多個SqlSessionTemplate的時候才需要指定它。對於一個MapperFactoryBean來說SqlSessionFactory和SqlSessionTemplate只需要其中一個就可以了,當兩者都指定了的時候,SqlSessionFactory會被忽略。
  • sqlSessionTemplateBeanName:指定需要使用的sqlSessionTemplate對應的bean名稱。

注意:由於使用sqlSessionFactory和sqlSessionTemplate屬性時會使一些內容在PropertyPlaceholderConfigurer之前加載,導致在配置文件中使用到的外部屬性信息無法被及時替換而出錯,因此官方現在新的Mybatis-Spring中已經把sqlSessionFactory和sqlSessionTemplate屬性廢棄了,推薦大家使用sqlSessionFactoryBeanName屬性和sqlSessionTemplateBeanName屬性。

 

Xml代碼  收藏代碼
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
  4.     xmlns:mvc="http://www.springframework.org/schema/mvc"  
  5.     xmlns:mybatis="http://www.mybatis.org/schema/mybatis"  
  6.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  7.      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  8.      http://www.springframework.org/schema/context  
  9.      http://www.springframework.org/schema/context/spring-context-3.0.xsd  
  10.      http://www.mybatis.org/schema/mybatis  
  11.      http://www.mybatis.org/schema/mybatis/mybatis-spring.xsd  
  12.      http://www.springframework.org/schema/mvc  
  13.      http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">  
  14.    
  15.     <context:component-scan base-package="com.tiantian.mybatis" />  
  16.     <context:property-placeholder location="classpath:config/jdbc.properties" />  
  17.     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"  
  18.        destroy-method="close">  
  19.        <property name="driverClassName" value="${jdbc.driver}" />  
  20.        <property name="url" value="${jdbc.url}" />  
  21.        <property name="username" value="${jdbc.username}" />  
  22.        <property name="password" value="${jdbc.password}" />  
  23.     </bean>  
  24.     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
  25.        <property name="dataSource" ref="dataSource" />  
  26.        <property name="mapperLocations" value="classpath:com/tiantian/mybatis/mapper/*.xml" />  
  27.        <property name="typeAliasesPackage" value="com.tiantian.mybatis.model" />  
  28.     </bean>  
  29.     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
  30.        <property name="basePackage" value="com.tiantian.mybatis.mapper" />  
  31.        <property name="markerInterface" value="com.tiantian.mybatis.mapper.SuperMapper"/>  
  32.        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>  
  33.     </bean>  
  34. </beans>  
 此方法配置好後,默認被註冊的接口名稱第一個字母小寫爲bean的名稱,如接口名IBlogMapper,bean名稱爲iBlogMapper,如此引用。

使用時,用接口生命,名稱和對應的bean名稱相同,然後spring自動注入bean,如此就將mybatis的數據源交給了spring管理。

SqlSessionTemplate

       除了上述整合之後直接使用Mapper接口之外,Mybatis-Spring還爲我們提供了一種直接使用SqlSession的方式。Mybatis-Spring爲我們提供了一個實現了SqlSession接口的SqlSessionTemplate類,它是線程安全的,可以被多個Dao同時使用。同時它還跟Spring的事務進行了關聯,確保當前被使用的SqlSession是一個已經和Spring的事務進行綁定了的。而且它還可以自己管理Session的提交和關閉。當使用了Spring的事務管理機制後,SqlSession還可以跟着Spring的事務一起提交和回滾。

       使用SqlSessionTemplate時我們可以在Spring的applicationContext配置文件中如下定義:

    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">

       <constructor-arg index="0" ref="sqlSessionFactory" />

    </bean>

       這樣我們就可以通過Spring的依賴注入在Dao中直接使用SqlSessionTemplate來編程了,這個時候我們的Dao可能是這個樣子:

 

Java代碼  收藏代碼
  1. package com.tiantian.mybatis.dao;  
  2.    
  3. import java.util.List;  
  4. import javax.annotation.Resource;  
  5. import org.mybatis.spring.SqlSessionTemplate;  
  6. import org.springframework.stereotype.Repository;  
  7. import com.tiantian.mybatis.model.Blog;  
  8.    
  9. @Repository  
  10. publicclass BlogDaoImpl implements BlogDao {  
  11.    
  12.     private SqlSessionTemplate sqlSessionTemplate;  
  13.    
  14.     publicvoid deleteBlog(int id) {  
  15.        sqlSessionTemplate.delete("com.tiantian.mybatis.mapper.BlogMapper.deleteBlog", id);  
  16.     }  
  17.    
  18.     public Blog find(int id) {  
  19.       returnsqlSessionTemplate.selectOne("com.tiantian.mybatis.mapper.BlogMapper.selectBlog", id);  
  20.     }  
  21.    
  22.     public List<Blog> find() {  
  23.        returnthis.sqlSessionTemplate.selectList("com.tiantian.mybatis.mapper.BlogMapper.selectAll");  
  24.     }  
  25.    
  26.     publicvoid insertBlog(Blog blog) {  
  27.        this.sqlSessionTemplate.insert("com.tiantian.mybatis.mapper.BlogMapper.insertBlog", blog);  
  28.     }  
  29.    
  30.     publicvoid updateBlog(Blog blog) {  
  31.        this.sqlSessionTemplate.update("com.tiantian.mybatis.mapper.BlogMapper.updateBlog", blog);  
  32.     }  
  33.      
  34.     public SqlSessionTemplate getSqlSessionTemplate() {  
  35.        returnsqlSessionTemplate;  
  36.     }  
  37.      
  38.     @Resource  
  39.     publicvoid setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {  
  40.        this.sqlSessionTemplate = sqlSessionTemplate;  
  41.     }  
  42.    
  43. }  
 注:

 

      本文是基於Mybatis3.2.1、Mybatis-Spring1.1.0和Spring3.1寫的。


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