mybatis-spring:mybatis在spring中的使用

當咱們想在 spring 項目中使用 mybatis 的時候就須要 mybatis-spring 了,它可讓 spring 完美的整合 mybatis 代碼。使用這個類庫中的類,spring 將會加載必要的 mybatis 工廠類和 session 類。 這個類庫也提供一個簡單的方式來注入 mybatis 數據映射器和 SqlSession 到業務層的 bean 中。 並且它也會處理事務, 翻譯 MyBatis 的異常到 Spring 的 DataAccessException 異常(數據訪問異常)中java

咱們先走一個簡單例子,再在基礎上擴展web

1、例子

一、添加依賴

使用 mybatis-spring 模塊,須要添加 mybatis-spring-x.x.x.jarspring

<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

二、建立 SqlSessionFactoryBean

咱們在使用 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

  • dataSource 屬性是必須的,配置數據源信息
  • configLocation 屬性用來指定 MyBatis 的 XML 配置文件路徑,若是基本的 MyBatis 配置須要改變(一般這會是<settings> 或<typeAliases>的部分)
  • mapperLocations 屬性用來指定映射器文件的資源位置

mapperLocations 能夠配置多個位置ide

<property name="mapperLocations">
    <list>
        <value>classpath*:conf/mybatis/**/*Mapper.xml</value>
        <value>classpath*:conf/com/brave/**/*Mapper.xml</value>
    </list>
</property>

三、使用 SqlSessionTemplate

在 mybatis 中,咱們使用 SqlSessionFactory 來建立 SqlSession。獲取了一個 session 以後,使用它來執行映射的 SQL 語句、提交或回滾鏈接,最後當再也不須要它的時候關閉 session。
使用 mybatis-spring 以後,就不須要直接使用 SqlSessionFactory 了,由於你的 bean 能夠經過一個線程安全的 SqlSession 來注入,基於 spring 的事務配置來自動提交、回滾、關閉 session。

1)SqlSessionTemplate

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 + "行");
    }
}

2) SqlSessionDaoSupport

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 的工做或須要具體的類,那麼這個類就頗有用了。

2、事務

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>

3、注入映射器

在 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

想要直接使用 數據映射器接口,先添加 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();
    }
}

二、MapperScannerConfigurer

咱們沒有必要在 spring 的 XML 配置文件中註冊全部的映射器。只用使用一個 MapperScannerConfigurer 便可,它會查找類路徑下的映射器並自動將它們建立成 MapperFactoryBean

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

這樣就不用每一個 mapper 都配置一個 MapperFactoryBean 了

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

三、@MapperScan 和 mybatis:scan

另外還有兩種掃描映射器的方法

  • <mybatis:scan> 元素
  • @MapperScan 註解

1) <mybatis:scan> 元素

<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>

2) @MapperScan

若是使用基於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);  
    }  
}
相關文章
相關標籤/搜索