【Spring06】Spring整合MyBatis

首先是需要用到的包:

<dependencies>
    <!-- spring 依赖-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- junit单元测试依赖-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
    </dependency>
    <!-- 导入MyBatis依赖-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>${mybatis.version}</version>
    </dependency>
    <!-- Spring整合mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>${mybatis-spring.version}</version>
    </dependency>
    <!-- MySQL驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.version}</version>
    </dependency>
    <!-- druid连接池-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>${druid.version}</version>
    </dependency>
</dependencies>

Spring整合MyBatis的核心是将MyBatis需要的重要的对象交由Spring工厂去管理,即将原本需要配置在mybatis-config.xml中的对象配置到Spring配置文件中去。

1 配置数据源

首先需要做的是将数据源配置到项目中。

1.1 引入jdbc.properties配置文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatisdb?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=1234

1.2 Spring配置文件配置jdbc.properties

原本在mybatis-config.xml配置文件中需要配置的jdbc连接池信息:

<!-- 核心配置信息-->
<environments default="mybatis_config">
    <!-- 数据库相关配置-->
    <environment id="mybatis_config">
        <!-- 事务类型-->
        <transactionManager type="jdbc"/>
        <!-- 数据库连接参数-->
        <dataSource type="com.qianglj.datasource.MyDruidDataSourceFactory">
            <property name="driverClass" value="${jdbc.driver}"/>
            <property name="jdbcUrl" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </dataSource>
    </environment>
</environments>

配置到Spirng的配置文件中:

 

<context:property-placeholder location="classpath:jdbc.properties"/>
<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>
  • <context:property-placeholder location="classpath:jdbc.properties"/>:引入解析相关properties取值表达式的组件;

除了以上基本信息的配置以外,还可以进行更加详细的配置:

<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}"/>
    <!-- 配置初始化大小、最小、最大 -->
    <property name="initialSize" value="${jdbc.init}"/>
    <property name="minIdle" value="${jdbc.minIdle}"/>
    <property name="maxActive" value="${jdbc.maxActive}"/>

    <!-- 配置获取连接等待超时的时间 ms-->
    <property name="maxWait" value="60000"/>

    <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
    <property name="timeBetweenEvictionRunsMillis" value="60000"/>

    <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
    <property name="minEvictableIdleTimeMillis" value="300000"/>
</bean>

当然jdbc.properties也需要进行对应的更新:

 

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatisdb?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=1234
jdbc.init=1
jdbc.minIdle=1
jdbc.maxActive=3

2 整合MyBatis

将SqlSessionFactory、Dao以及Service配置到Spring工厂中。

6.2.1 配置SqlSessionFactory

<!-- 生产:SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <!-- 注入连接池 -->
    <property name="dataSource" ref="dataSource"/>
    <!-- 注入dao-mapper文件信息 ,如果映射文件和dao接口 同包且同名,则此配置可省略-->
    <property name="mapperLocations">
        <list>
            <value>classpath:com/qianglj/dao/*.xml</value>
        </list>
    </property>
    <!-- 为 dao-mapper文件中的实体 定义缺省包路径
            如:<select id="queryAll" resultType="User"> 中 User类可以不定义包
        -->
    <property name="typeAliasesPackage" value="com.qianglj.entity"/>
</bean>
  • <value>classpath:com/qianglj/dao/*.xml</value>:存放Mapper.xml文件的路径,后续需要补全;

  • <property name="typeAliasesPackage" value="com.qf.entity"></property>:定义别名,规则和MyBatis一致,默认会用类名作为别名;

  • 至此,原mybatis-config.xml的内容已经全部配置至Spring工厂中;

进行测试:

@Test
public void test(){
    ApplicationContext ac = new ClassPathXmlApplicationContext("/applicationContext.xml");
    SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) ac.getBean("sqlSessionFactory");
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserDao mapper = sqlSession.getMapper(UserDao.class);
    List<User> users = mapper.queryUsers();
    for (User user : users) {
        System.out.println(user);
    }
}

2.2 配置MapperScannerConfigurer

MapperScannerConfigurer的作用是帮助我们将MyBatis的Dao实现放到工厂中去进行管理:

  • 扫描所有的Dao接口,去构建Dao实现;

  • 将Dao实现存入工厂管理;

  • Dao实现对象在工厂中的id是:首字母小写的接口类名。

<bean id="mapperScannerConfigurer9" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!-- dao接口所在的包  如果有多个包,可以用逗号或分号分隔
    <property name="basePackage" value="com.a.dao,com.b.dao"></property>
    -->
    <property name="basePackage" value="com.qianglj.dao"/>
    <!-- 如果工厂中只有一个SqlSessionFactory的bean,此配置可省略 -->
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

进行测试:

 

@Test
public void test2(){
    ApplicationContext ac = new ClassPathXmlApplicationContext("/applicationContext.xml");
    UserDao userDao = (UserDao) ac.getBean("userDao");
    List<User> users = userDao.queryUsers();
    for (User user : users) {
        System.out.println(user);
    }
}

2.3 配置Service

完整的Service实现类:

public class UserServiceImpl implements UserService {

    private UserDao userDao;

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public List<User> queryUsers() {
        return userDao.queryUsers();
    }
}

在工厂中配置Service:

<bean id="userService" class="com.qianglj.service.Impl.UserServiceImpl">
    <property name="userDao" ref="userDao"/>
</bean>

进行测试:

 

@Test
public void test3(){
    ApplicationContext ac = new ClassPathXmlApplicationContext("/applicationContext.xml");
    UserService userService = (UserService) ac.getBean("userService");
    List<User> users = userService.queryUsers();
    for (User user : users) {
        System.out.println(user);
    }
}

3 事务操作

将UserDao和对应的Mapper.xml文件补充完整,得到增删改查方法:

UserDao:

public interface UserDao {
    List<User> queryUsers();

    Integer insertUser(User user);

    Integer updateUser(User user);

    Integer deleteUser(Integer id);
}

对应的Mapper.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.qianglj.dao.UserDao">
    <select id="queryUsers" resultType="User">
        select id,username,password,gender,regist_time
        from t_user
    </select>

    <delete id="deleteUser" parameterType="int">
        delete from t_user
        where id=#{id}
    </delete>

    <update id="updateUser" parameterType="User">
        update t_user
        set username=#{username},password=#{password},gender=#{gender},regist_time=#{registTime}
        where id=#{id}
    </update>

    <insert id="insertUser" parameterType="User">
        <!-- 主键回填,将新数据的ID,存入java对象的和主键对应的属性中 -->
        <selectKey order="AFTER" resultType="int" keyProperty="id">
            select last_insert_id()
        </selectKey>
        insert into t_user values(#{id},#{username},#{password},#{gender},#{registTime})
    </insert>
</mapper>

3.1 配置DataSourceTransactionManager

事务管理器,可以帮助我们管理事务,进行提交、回滚等操作。

  • <property name="dataSource" ref="dataSource"/>:此处的dataSource需要和SqlSessionFactory注入同一个DataSource的Bean,否则的话事务控制会失败。

3.2 配置事务通知

事务管理在项目中属于额外功能,因此需要使用到AOP的相关功能。

<!-- 事务通知 -->
<tx:advice id="txManager" transaction-manager="tx">
    <!--事务属性-->
    <tx:attributes>
        <!--以User结尾的方法,切入此方法时,采用对应事务实行-->
        <tx:method name="*User"/>
        <!--剩余所有方法-->
        <tx:method name="*"/>
    </tx:attributes>
</tx:advice>
  • transaction-manager="tx":引入6.1中配置的DataSourceTransactionManager;

  • <tx:method name="*User"/>:可以针对不同的方法单独指定不同的事务属性,例如隔离级别、传播行为、读写性等等;

    • 可以为不同的业务方法定制合适的事务属性;

  • 可以配置的事务属性有:

    • 隔离级别,isolation:

      • deafult:默认值,采用数据库的默认的设置,建议使用;

      • read-uncommitted:读未提交;

      • read-committed:读已提交,Oracle数据库默认的隔离级别,可以防止脏读;

      • repeatable-read:可重复读,MySQL数据库默认的隔离级别,可以防止不可重复读;

      • serialized-read:序列化,可以防止幻读;

    • 传播行为,propagation:当涉及到事务嵌套(Service调用Service)时,可以设置

      • SUPPORTS不存在外部事务,则不开启新的事务;存在外部事务,则合并到外部事务中;适合查询;

      • REQUIRED不存在外部事务,则开启新事务;存在外部事务,则合并到外部事务中;默认值,适合增删改;

    • 读写性,read-only:

      • true:只读,可以提高查询效率;

      • false:可读可写,默认值;

    • 事务超时,timeout:当前事务所需要操作的数据如果被其他事务所占用,等待的时间;

      • 100:自定义等待时间,此处为100

      • -1:由数据库指定等待时间,默认值,建议;

    • 事务回滚,rollback-for:

      • 如果事务中抛出RuntimeException,则自动回滚;如果事务中抛出CheckException(非运行时异常Exception),则不会总动回滚,而默认会自动提交事务;

      • 设置rollback-for=Exception,则会自动回滚。

3.3 编织

<aop:config>
    <aop:pointcut id="pc_tx" expression="execution(* com.qianglj.service.Impl.UserServiceImpl.*(..))"/>
    <aop:advisor advice-ref="txManager" pointcut-ref="pc_tx"/>
</aop:config>

4 完整的配置文件

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <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}"/>
        <!-- 配置初始化大小、最小、最大 -->
        <property name="initialSize" value="${jdbc.init}"/>
        <property name="minIdle" value="${jdbc.minIdle}"/>
        <property name="maxActive" value="${jdbc.maxActive}"/>

        <!-- 配置获取连接等待超时的时间 ms-->
        <property name="maxWait" value="60000"/>

        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000"/>

        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="300000"/>
    </bean>

    <!-- 生产:SqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入连接池 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 注入dao-mapper文件信息 ,如果映射文件和dao接口 同包且同名,则此配置可省略-->
        <property name="mapperLocations">
            <list>
                <value>classpath:com/qianglj/dao/*.xml</value>
            </list>
        </property>
        <!-- 为 dao-mapper文件中的实体 定义缺省包路径
            如:<select id="queryAll" resultType="User"> 中 User类可以不定义包
        -->
        <property name="typeAliasesPackage" value="com.qianglj.entity"/>
    </bean>

    <!-- mapperScannerConfigurer   userDAO-->
    <bean id="mapperScannerConfigurer9" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- dao接口所在的包  如果有多个包,可以用逗号或分号分隔
           <property name="basePackage" value="com.a.dao,com.b.dao"></property>
        -->
        <property name="basePackage" value="com.qianglj.dao"/>
        <!-- 如果工厂中只有一个SqlSessionFactory的bean,此配置可省略 -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

    <bean id="userService" class="com.qianglj.service.Impl.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>

    <!-- 1. 引入一个事务管理器,其中依赖DataSource,借以获得连接,进而控制事务逻辑 -->
    <bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 事务通知 -->
    <tx:advice id="txManager" transaction-manager="tx">
        <!--事务属性-->
        <tx:attributes>
            <!--以User结尾的方法,切入此方法时,采用对应事务实行-->
            <tx:method name="*User"/>
            <!--剩余所有方法-->
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="pc_tx" expression="execution(* com.qianglj.service.Impl.UserServiceImpl.*(..))"/>
        <aop:advisor advice-ref="txManager" pointcut-ref="pc_tx"/>
    </aop:config>
</beans>

 

版权声明:
作者:jackqiang
链接:http://www.jackqiang.com/framework/spring/2013/spring_mybatis/
来源:JackQiang's
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>
文章目录
关闭
目 录