1、mybatis的事务:JDBC|Manage 默认不会自动提交。
2、spring集成mybatis的事务:事务默认是自动提交。
需要导入mybatis-spring-xxx.jar包 与 spring-tx-xxxx.jar包
本质:将事务交给了spring管理
事务:是逻辑上一组操作,要么全都成功,要么全都失败.
事物目的就是解决【数据不一致】的问题。
原子性:(A)事务不可分割
一致性(C):事务执行的前后,数据完整性保持一致.
隔离性(I):一个事务执行的时候,不应该受到其他事务的打扰
持久性(D):一旦结束,数据就永久的保存到数据库
如果不考虑隔离性,事务由3类读问题
脏读:一个事务读到另一个事务未提交数据
不可重复读:一个事务读到另一个事务已经提交数据(update)导致一个事务多次查询结果不一致
虚读:一个事务读到另一个事务已经提交数据(insert)导致一个事务多次查询结果不一致
事务解决并发操作3类读问题:设置隔离级别
并发访问丢失更新的问题:Java(锁)/数据库(锁)
设置事务的隔离级别,从某种程度上可以有效解决事务特性引起的3类读问题
未提交读: 以上情况都有可能发生。
已提交读: 避免脏读,但不可重复读,虚读是有可能发生。
可重复读: 避免脏读,不可重复读,但是虚读有可能发生。
串行的: 避免以上所有情况. 系统吞吐量很低
三层架构:web层:Servlet/jsp---->service层—>dao/mapper层
分层开发:事务处在Service层.
commit(TransactionStatus status)
getTransaction(TransactionDefinition definition)
rollback(TransactionStatus status)
ISOLation_XXX: 事务隔离级别.
PROPAGATION_XXX: 事务的传播行为.(不是JDBC中有的,为了解决实际开发问题.)
Timeout: 过期时间
是否有保存点
是否一个新的事务
事务是否已经提交
PlatformTransactionManager通过TransactionDefinition设置事务相关信息管理事务,
管理事务过程中,产生一些事务状态:状态由TransactionStatus记录.
Spring为不同的持久化框架提供了不同PlatformTransactionManager接口实现
org.springframework.jdbc.datasource.DataSourceTransactionManager
使用Spring JDBC或iBatis 进行持久化数据时使用
org.springframework.orm.hibernate3.HibernateTransactionManager
使用Hibernate3.0版本进行持久化数据时使用
org.springframework.orm.jpa.JpaTransactionManager
使用JPA进行持久化时使用
org.springframework.jdo.JdoTransactionManager
当持久化机制是Jdo时使用
org.springframework.transaction.jta.JtaTransactionManager
使用一个JTA实现来管理事务,在一个事务跨越多个资源时必须使用
接口: DataSourceTransactionManager
事务管理模板类:transactionTemplate
第1步:业务的层的哪些方法需要事务(黑客)
UserInfoServiceImpl1.zz(int from ,int to ,int money);//银行转账业务
@Component
public class UserInfoServiceImpl1 implements IUserInfoService {
@Autowired
private UserInfoMapper userInfoMapper;
@Autowired
private TransactionTemplate transactionTemplate;
// @Autowired
// public UserInfoServiceImpl1(PlatformTransactionManager transactionManager) {
// this.transactionTemplate = new TransactionTemplate(transactionManager);
// }
/**
* 转账业务:旺财(from)转账给来福(to),转money钱
*
* 旺财(from) 更新操作 减money 来福 (to) 更新操作 加money money =200
*
*
* zz(1,2,300)
*/
@Override
public void zz(int from, int to, int money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
//转账的操作
zzOptional(from, to, money);
System.out.println("转账成功");
} catch (Exception ex) {
System.out.println("转账失败,进行回滚");
status.setRollbackOnly();
}
}
});
}
private void zzOptional(int from, int to, int money) throws Exception{
// 一,==============旺财的钱减少300==============
// 1.1查询旺财有多少钱
UserInfo wc = userInfoMapper.selectByPrimaryKey(from);
System.out.println(wc);
// 1.2扣旺财有300
wc.setMoney(wc.getMoney() - money);
int result = userInfoMapper.updateByPrimaryKey(wc);
// ==============二,来福的钱增加300==============
// 1.1查询旺财有多少钱
UserInfo lf = userInfoMapper.selectByPrimaryKey(to);
System.out.println(lf);
// 1.2扣旺财有300
lf.setMoney(lf.getMoney() + money);
int result2 = userInfoMapper.updateByPrimaryKey(lf);
//==============最后的结果==============
if (result > 0 && result2 > 0) {
System.out.println("转账成功!!");
} else {
// int a = 10/0;//产生一个异常
throw new Exception("转账失败");// 产生一个异常
}
}
}
接口IUserInfoService
package com.cc.service;
public interface IUserInfoService {
/*
* from:转出的账户
* to:转入的账户
* money:转的金额
*
*/
public void zz(int from ,int to,int money);
}
第2步:xml中配置事务管理器 (不同的orm框架 事务管理的方式不同)
(orm框架:mybatis,hibernate,jpa,jdbcTemplate…)
创建spring-datasource.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="database.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${userName}" />
<property name="password" value="${password}" />
bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource">property>
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.cc.mapper">property>
bean>
<context:annotation-config/>
<context:component-scan base-package="com.cc">context:component-scan>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
bean>
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager">property>
bean>
beans>
第3步:在业务类定义TransatcionTemplate事务模板类
new TransatcionTemplate(事务管理器);
第4步:在需要事务管理的方法中
(就是第一个文件UserInfoServiceImpl1中的代码:)
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
updateOperation1();//持久层操作1 扣二狗子的300
updateOperation2();//持久层操作2 增加付自强300
} catch (SomeBusinessException ex) {
status.setRollbackOnly();
}
}
});
第5步:测试,调用业务类的方法
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-datasource.xml")
public class MyBatisSpringTest {
@Autowired
private UserInfoMapper userInfoMapper;
@Autowired
private UserInfoServiceImpl1 UserInfoServiceImpl1;
@Test
public void whenSelectSuccess() {
System.out.println(userInfoMapper.selectByExample(null));
}
@Test
public void whenZzSuccess() {
UserInfoServiceImpl1.zz(1, 2,100);
}
}