Spring提供了声明事务处理机制,它基于AOP的实现,无需编写任何事务管理代码,所有的工作全在配置文件中完成,与业务代码完全分离,配置即可用,降低了开发和维护的难度。
一、想要事务管理,就要对数据修改
1、在cn.bdqn下的dao层,创建UserMapper.xml文件,写入update修改语句,抽接口
<update id="updatePwdById" parameterType="User">
update smbms_user set userPassword = #{userPassword} where id = #{id}
</update>
抽接口
public int updatePwdById(User user);
2、在service层,创建UserServiceImpl,写入updatePwdById方法,抽接口
@Transactional(rollbackFor=Exception.class)
public int updatePwdById(User user){
int i = userMapper.updatePwdById(user);
System.out.println(1/0);
return i;
}
抽接口
public int updatePwdById(User user);
3、在添加事务前,先测试(UserMapperTest),如果是好使的,就可以修改
4、配置文件,加入事务管理器
①、id=”txManager” ②、注解管理事务
<!-- 添加/配置Spring的事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- name="dataSource"属性 ref="dataSource"数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 启用注解管理事务 -->
<tx:annotation-driven transaction-manager="txManager" />
二、声明式事务的注解添加方式
@Transactional
5、到userServiceImpl中的方法上面加入@Transactional(rollbackFor=Exception.class),添加回滚
6、测试,如果测试之前,方法上有@Transactional和回滚,测试时,密码不会 被修改;
如果测试之前,方法上没有@Transactional和回滚,测试时,密码才会 被修改;
7、开启回滚事务的作用?
//开启事务(添加回滚)—作用:方法内部可以调用多个Dao,多个sql语句加入同一事务,满足ACID的原则,
//如果发生异常,无论在什么位置,方法内所有已经执行了的sql语句均会发生回滚操作,从而保证事务的原子性,
//一致性,持久性。而隔离性需要看数据库的隔离级别去确定
三、事务的5种隔离级别
1、DEFAULT:默认值
2、READ_UNCOMMITED:未提交读——无锁——————-允许脏读、不可重复读、幻读
3、READ_COMMITED:提交读—————会话锁——————-允许不可重复读、幻读
4、REPEATABLE_READ:可重复读———行级锁——————-允许幻读
5、SERIALIZABLE:串行读———————表级锁——————都不允许
四、产生的三种问题
脏读:事务A读取到事务B还没有提交的事务
不可重复读:两次读取的数据不一致
幻读:事务A修改了数据,事务B添加了一条数据,事务A查看是修改好了,但是事务B修改后,事务A再次查看怎么多了一条
五、配置文件的拆分
拆分的策略,有两种
1、如果一个开发人员负责一个模块,采用公用配置(数据源、事务等)+每个模块的单独配置文件(dao、Service、和web控制器等)
2、如果开发是按照分层进行的分工,采用公用配置(数据源、事务等)+DAOBean配置+业务逻辑Bean配置+Web控制器配置的形式。
拆分实现
首先新建applicationContext-Mybatis.xml
将配置文件中的Spring整合mybatis的代码切入applicationContext,xml
测试前,在原先配置文件中引入子配置文件,再测试UserMapperTest
根配置文件中
<!-- 引入相关的子配置文件 525-->
<import resource="applicationContext-mybatis.xml"/>
子配置文件中
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<!-- spring整合mybatis -->
<!-- 1、声明bean 加载database.properties配置文件-->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:database.properties</value>
</property>
</bean>
<!-- 配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName">
<value>${driver}</value>
</property>
<property name="url">
<value>${url}</value>
</property>
<property name="username">
<value>${user}</value>
</property>
<property name="password">
<value>${password}</value>
</property>
</bean>
<!-- 声明sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource">
</property>
<property name="configLocation">
<value>classpath:mybatis-config.xml</value>
</property>
</bean>
<!-- 扫描指定Mapper的包,使其注册为Mapper对象 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage">
<value>cn.bdqn.dao</value>
</property>
</bean>
</beans>