前言
上一节介绍了Spring是如何整合Mybatis的,这一节是在此基础上结合Spring做事务管理。
讲解
我们将使用transactionManager方式做事务管理。
目录结构
源码
依旧从上到下依次介绍。
UserDaoImpl
这里我们增加了UserDaoImpl作为具体的执行有事务之间的隔离实现。并在原有的基础上增加了insertUser方法作为本次事务控制展示的方法。
package cn.ceres.architecture.integration.dao.impl;
import cn.ceres.architecture.integration.dao.UserDao;
import cn.ceres.architecture.integration.dao.model.User;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import javax.annotation.Resource;
@Repository
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
@Autowired
private DataSourceTransactionManager transactionManager;
@Resource
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
super.setSqlSessionFactory(sqlSessionFactory);
}
@Override
public User getUser(Long id) {
User user = this.getSqlSession().selectOne("cn.ceres.architecture.integration.dao.UserMapper.getUser", id);
return user;
}
@Override
public void insertUser(User user) {
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = transactionManager.getTransaction(def);
this.getSqlSession().insert("cn.ceres.architecture.integration.dao.UserMapper.insertUser", user);
transactionManager.commit(status);
}
}
User
依旧是那个PoJo类,作为数据层的映射,做了一点点的改动就是将long改成了包装类型Long
package cn.ceres.architecture.integration.dao.model;
public class User {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
UserDao
这里我们增加了UserDao,作为接口方法的定义,具体实现参照UserDaoImpl
package cn.ceres.architecture.integration.dao;
import cn.ceres.architecture.integration.dao.model.User;
public interface UserDao {
public User getUser(Long id);
public void insertUser(User user);
}
UserMapper
这个接口在这里已经不需要了,可以删除
UserMapper.xml
这里增加了insertUser的Sql实现
<?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="cn.ceres.architecture.integration.dao.UserMapper">
<resultMap id="userMap" type="cn.ceres.architecture.integration.dao.model.User">
<id column="id" property="id"/>
<result column="name" property="name"/>
</resultMap>
<!-- 查询 此处如果多参数,建议使用Bean作为参数体-->
<select id="getUser" parameterType="java.lang.Long" resultMap="userMap">
SELECT
<include refid="QUERY_COLUMN_LIST"/>
FROM
<include refid="TABLE"/>
WHERE
id = #{id}
</select>
<!-- 查询 此处如果多参数,建议使用Bean作为参数体-->
<insert id="insertUser" useGeneratedKeys="true" parameterType="cn.ceres.architecture.integration.dao.model.User">
INSERT INTO
<include refid="TABLE"/>
(`name`)
VALUES
(#{name})
</insert>
<!-- 所有查询列 -->
<sql id="QUERY_COLUMN_LIST">
<![CDATA[
`id`,`name`
]]>
</sql>
<!-- 表-->
<sql id="TABLE"><![CDATA[ user ]]></sql>
<!-- 全部条件(更多功能可以通过queryData扩展实现) -->
<sql id="QUERY_WHERE_CLAUSE">
<where>
<if test="id != null and id != ''"><![CDATA[AND `id` = #{id}]]></if>
<if test="name != null and name != ''"><![CDATA[AND `name` = #{name}]]></if>
</where>
</sql>
<!-- 智能排序与分页 -->
<sql id="QUERY_ORDER_LIMIT_CONDITION">
<if test="orderField != null and orderField != '' and orderFieldType != null and orderFieldType != ''"><![CDATA[ORDER BY ${orderField} ${orderFieldType}]]></if>
<if test="startIndex != null and startIndex >= 0 and pageSize != null and pageSize > 0"><![CDATA[LIMIT #{startIndex},#{pageSize}]]></if>
</sql>
</mapper>
spring-config-dao.xml
这里不再使用MapperScannerConfigurer作代理,并且在sessionFactory内增加了mapperLocations属性节点,作为映射文件的扫描
<?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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.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"
default-autowire="byName">
<!-- BoneCP configuration -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${spring.datasource.username}"/>
<property name="password" value="${spring.datasource.password}"/>
<property name="jdbcUrl" value="${spring.datasource.url}"/>
<property name="driverClass" value="${spring.datasource.driverClassName}"/>
<property name="acquireIncrement" value="${spring.datasource.c3p0.acquireIncrement}"/>
<property name="idleConnectionTestPeriod" value="${spring.datasource.c3p0.idleConnectionTestPeriod}"/>
<property name="initialPoolSize" value="${spring.datasource.c3p0.initialPoolSize}"/>
<property name="maxIdleTime" value="${spring.datasource.c3p0.maxIdleTime}"/>
<property name="maxPoolSize" value="${spring.datasource.c3p0.maxPoolSize}"/>
<property name="minPoolSize" value="${spring.datasource.c3p0.minPoolSize}"/>
<!--增加 数据库库测试连接-->
<!--<property name="automaticTestTable" value="c3p0_test"/>-->
<!--<property name="testConnectionOnCheckin" value="true"/>-->
<property name="preferredTestQuery" value=" select 1 "/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- Transaction Manager -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 启用事务注解 -->
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="mapperLocations" value="classpath:cn/ceres/architecture/integration/dao/*Mapper.xml" />
<property name="dataSource" ref="dataSource"/>
</bean>
<!--自动查找类路径下的映射器并将它们自动装配-->
<!--<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">-->
<!--<property name="sqlSessionFactoryBeanName" value="sessionFactory" />-->
<!--<property name="basePackage" value="cn.ceres.architecture.integration.dao"/>-->
<!--</bean>-->
</beans>
application.properties
用于替换配置文件中的属性占位符
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:28827/architecture_integration?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=passw0rd
spring.datasource.c3p0.acquireIncrement=2
spring.datasource.c3p0.idleConnectionTestPeriod=50
spring.datasource.c3p0.initialPoolSize=5
spring.datasource.c3p0.maxIdleTime=90
spring.datasource.c3p0.maxPoolSize=3
spring.datasource.c3p0.minPoolSize=1
总结
这一节使用的是编程的方式控制事务。