1.什么是事务?
保证业务操作完整性的一种数据库机制
事务的特点:ACID
原子性 一致性 隔离性 持久性
2.如何控制事务
JDBC:
Connection.setAutoCommit(false);事务开启
Connection.commit();
Connection.rollback();
Mybatis:
Mybatis自动开启事务
sqlSession(底层封装了Connection).commit();
sqlSession.rollback();
结论:控制事务的底层 都是Connection对象完成的。
3.Spring控制事务的开发
Spring是通过AOP的方式进行事务开发。
1.原始对象
public class XXXSerServiceImpl{
private xxxDAO xxxDAO
set();get();
1.原始对象-->原始方法--》核心功能(业务处理+DAO调用)
2.DAO作为Service的成员变量,依赖注入的方式进行赋值。
}
2.额外功能
Spring为我们封装好了下图橙色的代码(开启事务,提交事务,遇到异常回滚事务),但是需要Connection,所以要为其注入连接池DataSource
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入连接池-->
<property name="dataSource" ref="dataSource"/>
//ref引入的dataSource是Spring与Mybatis整合时连接数据库那里的配置连接代码,此处省略
</bean>
3.切入点
@Transactional
事务的额外功能接入给哪些业务方法
1.加在类上:类中的所有方法都会加入事务
2.方法上:这个方法会加入事务
4.组装切面
1.切入点 2.额外功能
通过标签完成组装
<tx:annotation-driven transaction-manager="">
//切入点会自动扫描注解@Transactional
//transaction-manager=""指定额外功能
4.Spring控制事务的编码
1.搭建开发环境(jar)
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.14.RELEASE</version>
</dependency>
2.编码
@Transactional
public class UserServiceImpl implements UserService{
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
//Service只写核心功能和DAO的调用
@Override
public void register(User user) {
userDao.save(user);
}
}
<!-- 此处省略Spring与Mybatis整合的.xml配置-->
1.原始对象
<bean id="userService" class="com.dy.service.UserServiceImpl">
<!-- 给userDao 注入 -->
<property name="userDao" ref="userDao"/>
</bean>
2额外事务.<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入连接池-->
<property name="dataSource" ref="dataSource"/>
</bean> //ref引入的dataSource是Spring与Mybatis整合时连接数据库那里的配置连接代码
3.切入点是ava代码的注解@Transactional
4组装
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
</beans>
测试:
细节1:如何证明额外事务已加入到register()方法中?
public void register(User user) {
userDao.save(user);
throw new RuntimeException("测试");
}
此时再次测试数据插入失败,抛出异常,执行了回滚操作(原子性:有一个错全部回滚)。所以额外功能已加入其中。
细节2:加入proxy-target-class属性进行底层动态代理的切换,默认为false动态代理是jdk(代理类实现原始类接口),
改成true是cglib(代理类没有实现接口,继承原始类)。
<tx:annotation-driven transaction-manager="dataSourceTransactionManager" proxy-target-class="true"/>