1、声明式事务与编程式事务:
1.1、配置声明式事务:spring的声明式事务是基于通知advice的
此处一般配置业务层(service层)需要事务管理的方法,例如新增、修改、删除的方法
1.2、编程式事务与声明式事务的区别:
1、编程式事务是手写事务控制代码
2、声明式事务的代码已经由spring写好,只需要声明那些方法需要进行事务控制和如何进行事务控制就好。
2、spring声明式事务配置:
ApplicationContext.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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd"
default-autowire="byName"
>
<!--加载属性文件-->
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!--数据库连接信息-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${dataSources.driver}"></property>
<property name="url" value="${dataSources.url}"></property>
<property name="username" value="${dataSources.username}"></property>
<property name="password" value="${dataSources.password}"></property>
</bean>
<!--事务管理器类:包spring-jdbc下的dataSource中的类-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--全局配置了使用byName配置了自动注入,此处默认使用全局配置,可以不用配置property-->
<!--<property name="dataSource" ref="dataSource"></property>-->
</bean>
<tx:advice id="interceptor" transaction-manager="txManager">
<tx:attributes>
<!--配置哪些方法需要事务控制 和 如何进行事务控制
使用<tx:method name=""/>标签配置哪些方法需要事务控制,name=""配置方法名
在该标签中,关于方法的事务配置有五个较常用属性:read-only=""、isolation=""、no-rollback-for=""、rollback-for=""、propagation=""
<tx:method name="insert"/>
<tx:method name="ins*"/>
<tx:method name="upd*"/>
<tx:method name="delete*"/>
<!--补充配置,事务配置只读-->
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
<!--切点方法配置,此处主要用于事务的配置,可以使用通配符把切点的范围配置的尽可能大-->
<aop:config>
<aop:pointcut id="pointCut" expression="execution(* service.Impl.*.*(..))"></aop:pointcut>
<aop:advisor advice-ref="interceptor" pointcut-ref="pointCut"></aop:advisor>
</aop:config>
</beans>
注:声明式事务配置在配置文件头部需要添加文件
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd"
业务层代码(接口省略,此出不展示):
package service.Impl;
import model.User;
import service.IUserService;
import java.util.List;
public class UserService implements IUserService {
@Override
public User insert(User user) {
return user;
}
public User insUser(User user){
User u= insert(user); //调用
return u;
}
@Override
public User updateUser(User user) {
return null;
}
@Override
public void deleteUserById(int id) {
}
@Override
public List<User> queryAll() {
return null;
}
}
数据库属性文件–db.properties:
dataSources.driver=com.mysql.jdbc.Driver
dataSources.url=jdbc:mysql://localhost:3306/mybatis
dataSources.username=root
dataSources.password=root
3、配置事务控制方法标签的属性简介:
配置哪些方法需要事务控制 和 如何进行事务控制
使用<tx:method name=""/>标签配置哪些方法需要事务控制,name="“配置方法名
在该标签中,关于方法的事务配置有五个较常用属性:read-only=”"、isolation=""、no-rollback-for=""、rollback-for=""、propagation=""
3.1、read-only="":取值true/false,是否是只读事务
3.1.1、如果取值true,则事务为只读事务,查询方法建议都是用该属性值,只读事务对数据库优化有一定效果,可以提升性能;
3.1.2、如果取值false, 该值为默认值,事务需要提交事务,主要新增、更新、删除操作需要。
3.2、isolation="":取值DEFAULT、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE,事务的隔离级别配置。
在多线程或者并发访问下如何保证访问到的数据具有完整性(隔离性)。
数据库隔离性分析:脏读、不可重复读、幻读
脏读:事务A读取到事务B中未提交的数据,事务B中的数据放生改变,事务A中读取到的数据可能和数据苦衷的数据不一致,此时认为数据是
脏数据,读取数据的过程叫做脏读。
不可重复读:主要针对的是更新操作,针对的是某一条数据或者某一条数据中的某列数据,两次读取在同一个事务中,当事务A第一次读取数据后,
事务B对事务A读取的数据进行了修改,事务A再次读取的数据与第一次读取的数据不一致,该过程叫做不可重复去。
幻读:幻读主要针对的是新增或者删除操作,两次读取在两个事务中,当事务A查询出数据,事务B在此时新增了一条数据,事务A中读取的数据
与数据中的数据就不一致了,该过程叫做幻读。
DEFAULT:默认值,该值的意义是要底层的数据库判断具体要执行什么隔离级别;
READ_UNCOMMITTED:可能读取到未提交的数据,可能出现脏读、不可重复读、幻读;此隔离级别效率较高
READ_COMMITTED:只能读取到其他事务已经提交的数据,可以防止脏读,但是可能出现不可重复读和幻读。
REPEATABLE_READ:读取的数据添加了锁,因此可以防止脏读、不可重复读,但是可能出现幻读。
SERIALIZABLE:队列曹组偶,对整个表添加了锁,因此在一个事务操作表数据时,另外的事务只能等待该事务完成才能操作表中数据,
此级别是最安全的,但是也是效率最低的。
3.3、propagation="":取值REQUIRED(默认值)、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED,控制事务传播行为
当一个具有事务控制的方法被另外一个有事务控制的方法调用,应该如何管理事务(新建事务、在事务中执行,将事务挂起、报异常)
REQUIRED**(默认值)**:如果当前有事务就在事务中执行,如果当前没有事务就新建一个事务。
SUPPORTS:如果当前有事务就在事务中执行,如果当前没有事务就在非事务的状态下执行;
MANDATORY:此值表示必须在事务中执行,如果有事务就在当前事务中执行,如果没有就会报异常;
REQUIRES_NEW:也是必须要在事务中执行,如果当前有事就将当前事务挂起,新建事务执行,如果当前没有事务就会新建事务;
NOT_SUPPORTED:必须在非事务状态下执行,如果当前没有事务就正常执行,如果当前有事务,会将事务挂起;
NEVER:必须在非事务状态下执行,如果当前没有事务正常执行,如果当前有事务就会报错;
NESTED:必须在是事务状态执行,如果当前没有事务就创建一个事务,如果当前有事务就会创建一个嵌套事务。
**3.4、rollback-for="":**值是异常的全限定类名,例如:java.lang.Exception,表示当出现哪类异常时会进行回滚,需要注意的是,当有手动写
抛出异常时,此处一定要进行异常配置。
3.5、no-rollback-for="":取值与上述一致,表示当出现什么异常不必回滚操作。