MyBatis及Spring事务初学总结
MyBatis是从iBatis项目继承而来,是目前互联网公司的主流数据访问层框架。
在实际使用中与Spring一起使用。MyBatis出了MyBatis-Spring组件,用于两者之间的整合,使用Spring的事务管理功能。
92 <dependency> 93 <groupId>org.mybatis</groupId> 94 <artifactId>mybatis-spring</artifactId> 95 <version>1.2.2</version> 96 </dependency>
DataSourceTransactionManager是Spring框架的组件,通过java.sql.connection来管理事务(通过commit()提交事务,或者通过rollback()回滚事务)
使用MyBatis的事务有两种方式:1.注解驱动;2.XML驱动
38 <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx --> 39 <bean id="transactionManager" 40 class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 41 <property name="dataSource" ref="dataSource" /> 42 </bean> 43 44 <tx:advice id="userTxAdvice" transaction-manager="transactionManager"> 45 <tx:attributes> 46 <tx:method name="delete*" propagation="REQUIRED" read-only="false" 47 rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException" /> 48 <tx:method name="insert*" propagation="REQUIRED" read-only="false" 49 rollback-for="java.lang.Exception" /> 50 <tx:method name="update*" propagation="REQUIRED" read-only="false" 51 no-rollback-for="java.lang.RuntimeException" rollback-for="java.lang.Exception"/> 52 <tx:method name="find*" propagation="SUPPORTS" /> 53 <tx:method name="get*" propagation="SUPPORTS" /> 54 <tx:method name="select*" propagation="SUPPORTS" /> 55 <tx:method name="*Transaction*" no-rollback-for="java.lang.RuntimeException" rollback-for="java.lang.Exception"/> 56 </tx:attributes> 57 </tx:advice> 58 59 <aop:config> 60 <aop:pointcut id="pc" 61 expression="execution(public * com.service.impl.*.*(..))" /> <!--把事务控制在Service层 --> 62 <aop:advisor pointcut-ref="pc" advice-ref="userTxAdvice" /> 63 </aop:config> 64 65 66 <!-- 创建SqlSessionFactory,同时指定数据源 --> 67 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 68 <property name="configLocation" value="/WEB-INF/mybatis-config.xml"></property> 69 <property name="dataSource" ref="dataSource" /> 70 </bean>
dataSource是通过dataSource.properties来进行配置的(这里有疑问,这样实现的话,spring的事务框架连接数据库时使用的就是com.mysql.jdbc.Driver,就没有连接池管理功能了吧?)
一般如下配置
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/myfirstbase
username=XXXX
password=XXXX
而mybatis-config.xml中一般配置的是
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTDConfig 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 6 <!-- mybatis的数据类型和处理器等等...都可以实现接口重写,然后配置 --> 7 <configuration> 8 9 <typeAliases> 10 <package name="com.model" /> 11 </typeAliases> 12 13 <mappers> 14 <!--映射文件--> 15 <mapper resource="com/mapper/userMapper.xml"/> 16 </mappers> 17 </configuration>
而userMapper.xml一般如下,同时需要一个interface,定义这些方法。
<?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 6 7 <mapper namespace="com.mapper.IUserMapper"> 8 9 <select id="selectAllUser" resultMap="UserMapper"> 10 select * from TEST_LEE 11 </select> 12 13 <resultMap type="User" id="UserMapper" autoMapping="true"> 14 <id property="id" column="id"/> 15 <result property="name" column="name"/> 16 <result property="user_id" column="user_id"/> 17 </resultMap> 18 19 <select id="selectById" parameterType="int" resultType="User"> 20 select * from TEST_LEE where id=#{id} 21 </select> 22 23 24 <insert id="insertUser" parameterType="User"> 25 insert into TEST_LEE (user_id, name) values(#{user_id},#{name}) 26 </insert> 27 28 <update id="updateUser" parameterType="User"> 29 update TEST_LEE set name=#{name}, user_id=#{user_id} where id=#{id} 30 </update> 31 32 <delete id="deleteUser" parameterType="int"> 33 delete from TEST_LEE where id=#{id} 34 </delete> 35 36 <!-- 返回自增ID会赋值到User.id --> 37 <insert id="insertResultGeneratedKey" parameterType="User" useGeneratedKeys="true" keyProperty="id"> 38 insert into TEST_LEE (user_id, name) values(#{user_id},#{name}) 39 </insert> 40 41 </mapper>
这其中的sqlSessionFactory是用Spring的SqlSessionFactoryBean来配置创建的,但是一般不直接使用,而是将其注入到了org.mybatis.spring.mapper.MapperFactoryBean中,或者其他扩展了SqlSessionDaoSupport的DAO中。
109 <!-- Mapper接口所在包名,Spring会自动查找其下的Mapper --> 110 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 111 <property name="basePackage" value="com.mapper" /> 112 </bean> 113 114 <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> 115 <property name="mapperInterface" value="com.mapper.IUserMapper" /> 116 <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> 117 </bean>
SqlSessionTemplate是MyBatis-Spring的核心类,负责管理MyBatis的SqlSession,调用MyBatis的SQL方法,翻译异常等,但是
为了代替手动使用SqlSessionDaoSupport或SqlSessionTemplate,MyBatis-Spring提供了一个动态代理的实现,即MapperFactoryBean,从而直接注入数据映射器到Service层bean中,MapperFactoryBean负责处理SqlSession的创建和关闭,使用了Spring事务后,事务完成时,session将会提交或者回滚。
2.Spring的事务的传播行为和隔离级别
提及Spring中的声明式事务,通常提及特性包括:事务的传播行为、隔离级别、只读、事务超时、回滚规则,可以参见上面的规则定义。
其中事务的传播行为有7种,比较常见的是REQUIRED、SUPPORTS、REQUIRES_NEW、NESTED。可参考这里的图示http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html#tx-propagation
具体列出如下
PROPAGATION_MANDATORY 强制的,表示该方法必须运行在一个事务中,否则抛出异常
PROPAGATION_NESTED 嵌套的,若当前已经有一个事务,则这个方法在其中在运行于一个嵌套其中的事务,可独立的提交或回滚
PROPAGATION_NEVER 不应该运行在事务中,如果一个事务正在运行则抛出异常
PROPAGATION_NOT_SUPPORTED 不应该运行在事务中,如果一个事务正在运行,则将该事务挂起
PROPAGATION_SUPPORTS 不需要事务上下文,但是也支持,如果有一个事务已经在运行,则该方法也可以在事务中运行
PROPAGATION_REQUIRES_NEW 需要新的事务。表示需要一个新的事务,如果一个现有事务正在运行,则该现有事务将被挂起
PROPAGATION_REQUIRED 需要事务,如果现在一个现有事务正在运行,则该方法直接在该事务中运行,否则起个新的事务
PROPAGATION_NESTED can only be used with a DataSourceTransactionManager and a JDBC3 driver. It uses save points in order to be able to rollback some part of a transaction (i.e. what constitutes the nested transaction in Spring terms). See the javadoc of Connection to see how save points work.
事务的隔离级别5种,用于说明受其他并发的事务的影响程度,通过锁表完全隔离当然可以做到没有影响,但这种情况下性能损失太大,并不适用所有场景。
ISOLATION_DEFAULT 默认的,适用数据库后端设置
ISOLATION_READ_UNCOMMITTED 允许读取尚未提交的更改。可能导致Dirty read、Phantom reads或Nonrepeatable read。
ISOLATION_READ_COMMITTED 允许从已经提交的并发事务读取,不会出现Dirty read,但是会出现Phantom reads或Nonrepeatable read。
ISOLATION_REPEATABLE_READ 对相同字段的多次读取需一直。不会出现Dirty read或Nonrepeatable read,但是还是可能出现Phantom read。
ISOLATION_SERIALIZABLE 完全服从ACID(原子性、一致性、隔离性、持久性)原则,确保不会出现Dirty read、Nonrepeatable read或Phantom read。
事务超时
事务只读
事务回滚规则:默认情况下只对继承自RuntimeException的异常(Unckecked Exception)进行回滚。
3.MyBatis涉及到分库分表怎么办
分库分表要解决的问题是因数据库存储量大了和访问量大了进行的水平扩展问题
这里可以参考这几个链接,
https://github.com/makersoft/mybatis-shards
其中CobarClient是阿里的解决方案
ShardBatis:http://code.google.com/p/shardbatis/
参考资料:
1.《Spring in action》
2.https://mybatis.github.io/mybatis-3/index.html
3.https://guptavikas.wordpress.com/2010/04/15/aspectj-pointcut-expressions/
4.https://www.ibm.com/developerworks/cn/education/opensource/os-cn-spring-trans/
5.http://m.oschina.net/blog/120707
6.http://gemantic.iteye.com/blog/1622799
7.http://www.douban.com/note/227015659/
posted on 2015-07-07 12:45 majia1949 阅读(1795) 评论(0) 编辑 收藏 举报