事务
事务是用户定义的一个操作序列。事务认为,这些操作序列是一个不可分割的工作单位。
事务有四个特点:原子性、一致性、隔离性和持久性。
用一句话来表述:一个业务要么全部成功,要么全部失败。
事务的原子性,表示事务执行过程中,用户定义的操作序列要么全部执行成功,要么全部执行失败。
事务的一致性,表示当事务执行失败时,所有被该事务影响的数据都应该恢复到事务执行前的状态,这称为事务回滚。
事务的隔离性,表示在事务执行过程中对数据的修改,在事务提交之前对其他事务不可见。
事务的持久性,表示事务完成之后,对系统的影响是永久性的。如果已提交的数据在事务执行失败时,数据的状态都应该正确。
使用事务时,要求数据库引擎必须是 InnoDB 引擎
JDBC实现事务的方式
1、保证一个业务的所有更新操作中。所使用的连接对象是同一个连接对象
2、将连接对象的提交方式设置为手动提交。
con.setAutoCommit(false);
通过 con.commit()提交事务
如果有异常发送时,可以通过com .rollbac()回滚事务
事务的并发问题
当两个或两个以上的线程,同时访问同一条记录时,就存在事务并发问题,可能造成数据混乱。
1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的就是脏数据。
2、不可重复读:事务A多次读取同一数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。
3、幻读:事务A对数据库的数据进行批量操作。事务B完成记录的添加,这时新加的记录可能就没有进行事务A的批量操作。这就是幻读。
解决事务并发问题,需要采用事务隔离级别来进行。
READ_UNCOMMITTED:未提交读,该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读。
READ_COMMITTED:提交读,该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读。
REPEATABLE_READ:可重复读,该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读。
SERIALIZABLE:串行读,所有事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读和幻读。但是这将严重影响程序的性能。
代理模式:在目标方法执行前或执行后,添加非功能性逻辑。
代理模式分为静态代理和动态代理。
面向切面编程,是一种通过预编译方式和运行期间,动态代理实现程序功能的同一维护技术。
面向切面编程的实现,是代理模式来运行的。代理模式可以针对某个目标对象进行代理。在目标对象执行方法前,或执行方法后,添加非功能性业务操作。
Spring AOP 对动态代理进行了封装,Spring AOP 框架将分散在系统中的功能块放到一个地方 -切面。
AOP术语:
切面(Aspect):就是你要实现的交叉的非核心业务功能 连接点(Joinpoint):应用程序执行过程中插入切面的地点,可以是方法调用,异常抛出……
通知(Advice):通知切面的实际实现代码
切入点(Pointcut):定义通知应用在哪些连接点
目标对象(Target):被通知的对象
代理(Proxy):将通知应用到目标对象后创建的对象
织入(Weaving):将切面应用到目标对象从而创建一个新的代理对象的过程
通知类型:
前置通知:在目标方法执行前,添加非功能性业务。 后通知:在目标方法执行后,添加非功能性业务。 环绕通知:在目标方法执行前,执行后,添加非功能性业务。 抛出异常通知,在目标方法抛出异常时,添加非功能性业务。
事务传播行为
事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的行为。
@Transactional 注解的 propagation 属性,用于定义事务传播行为 @Transactional( propagation = Propagation.REQUIRED)
Propagation.REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
Propagation.REQUIRES_NEW:创建一个新的食物,如果当前存在事务,则把当前事务挂起。
Propagation.SUPPORTS:如果当前存在事务 ,则加入该事务;如果当前没有事务,则以非事务方式继续运行。
Propagation.NOT_SUPPORTS:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
Propagation.NEVER:以非事务的方式运行,如果当前存在事务,则抛出异常。
Propagation.MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
事务的隔离级别是指若干个并发的事务之间的隔离程度
@Transactional 注解的 isolation 属性,用于定义事务隔离级别。
@Transactional(isolation = Isolation.READ_COMMITTED)
isolation= Isolation.READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读。
isolation = Isolation.REPEATABLE_READ: 该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读
isolation = Isolation.SERIALIZABLE: 所有事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读,不可重复读以及幻读。但是这将严重影响程序的性能。
isolation = Isolation.READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但是还没有提交的数据。该级别不能防止脏读,不可重复读和幻读。
AOP 环境搭建
1、导入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.19.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
2、创建目标接口和目标对象
public interface IUserService {
public void add();
public void del();
public void update();
}
@Service
public class UserServiceImpl implements IUserService {
@Override
public void add() {
System.out.println("执行添加");
}
@Override
public void del() {
System.out.println("执行删除");
}
@Override
public void update() {
System.out.println("执行修改");
}
}
3、创建切面类
@Component
@Aspect//标识该类为切片类
public class CutUtil {
//第一个星号表示方法任意返回类型
//com.project.service.. 表示匹配指定包及子包中的类
//*.* 匹配任何类的任何方法
//(..) 匹配方法任何参数
//表示com.project.service 包中所有类,在执行所有方法时,都会调用该方法
@Before("execution(* com.project.service..*.*(..))")
public void before(){
System.out.println("before前置通知");
}
@After("execution(* com.project.service..*.*(..))")
public void after(){
System.out.println("after后置通知");
}
@Around("execution(* com.project.service..*.*(..))")
public Object around(ProceedingJoinPoint point){
//得到目标对象
Object target = point.getTarget();
try {
//执行目标方法,得到方法执行后的返回值
Object returnObj = point.proceed();
System.out.println("环绕后");
return returnObj;
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
@AfterThrowing(value = "execution(* com.project.service..*.*(..))",
throwing = "e")
public void throwException(JoinPoint point,Exception e){
//得到目标对象
Object targetObj = point.getTarget();
//得到执行目标方法名
String methodName = point.getSignature().toString();
System.out.println("执行"+targetObj.getClass().getSimpleName()+"的"+
methodName+"方法,抛出"+e.getClass().getSimpleName()+"异常");
}
}
4、创建AOP配置类
@Configuration//标识该类为配置类
@ComponentScan("com.project")//扫描指定包及子包中的spring组件类
@EnableAspectJAutoProxy//添加自动代理
public class AopConfig {
}
今天的文章Java事务详解_java基础知识点整理分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/78201.html