BBS论坛项目相关-5:评论模块

本文讨论了BBS论坛项目中评论模块的事务管理,包括ACID属性和并发异常。介绍了不同的隔离级别,如读取未提交、读取已提交、可重复读和串行化。详细讲解了悲观锁和乐观锁的实现机制,并阐述了Spring的声明式和编程式事务管理,以及基于注解的事务配置。同时,提到了常用的事务传播机制,如REQUIRED、REQUIRES_NEW、NESTED等,最后讨论了评论功能的实现细节,包括评论属性、查询与添加评论的事务处理。
摘要由CSDN通过智能技术生成

BBS论坛项目相关-5:评论模块

事务管理

事务管理:ACID
常见并发异常:
第一类丢失更新,第二类丢失更新
脏读、不可重复读、幻读

第一类丢失更新:某个事务的回滚,导致另一个事务已更新数据丢失了。
第二类丢失更新:某个事务的提交,导致另一个事务已更新的数据丢失了。
脏读:某个事务读取了另一个事务未提交的数据。
不可重复读:某个事务对同一数据前后读取的结果不一致。
幻读:某一个事务对同一个表前后查询的行数不一致。

常见的隔离级别:
读取未提交数据(最低,以上并发异常都可能出现)
读取已提交数据
可重复读
串行化

实现机制:
悲观锁(数据库)
—共享锁(S锁):事务A对某数据加了共享锁后,其他事务只能对该数据加共享锁,但不能加排他锁
—排他锁(X锁):事务A对某数据加了排他锁后,其他事务对该数据既不能加共享锁,也不能加排他锁。
乐观锁(自定义)
–版本号,时间戳等
在更新数据前,检查版本号是否发生变化。若发生变化则取消本次更新,否则更新数据(版本号+1)。

Spring事务管理:
声明式事务:通过xml配置,声明某方法的事务特征;通过注解,声明某方法的事务特征
编程式事务:通过TransactionTemplate管理事务,并通过它执行数据库的操作
1.编程式事务 使用Transaction Ttempleate或者直接使用底层的Platform TransactionManager.对于编程式事务管理,spring推荐使用Transaction Template
  简单的说就是在代码中需要直接加入处理事务的逻辑,可能需要在代码中显式调用begin Transaction() commit(). rollback() 等事务管理相关的方法,如在执行a方法的时候需要事务处理,你需要在a方法开始时候开启事务,处理完成之后,在方法结束的时候,关闭事务.
2.声明式事务 建立在AOP之上的,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务,声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需要在配置文件中做相关的事务规则声明(或通过基于@Transaction注解的方式),便可以将事务规则应用到业务逻辑中.
  显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式.声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持.和编程式事务相比,声明式事务唯一不足的地方是,它的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别.但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等.
  声明式事务管理也有两种常用的方式,一种是基于tx和aop名字的xml配置文件,另一种就是基于@Transaction注解.显然基于注解的方式更简易.更清爽.
以Mybatis为例,基于注解的声明式事务配置

常用传播机制:
REQUIRED:支持当前事务(外部事务),如果不存在则创建事务
REQUIRES_NEW:创建一个新事务,并暂停当前事务(外部事务)
NESTED:如果当前存在事务(外部事务),则嵌套在该事务中执行
事务传播机制只适用于不同bean之间方法的调用,如果一个bean中的两个方法互相调用并不会使用到事务传播。
事务方法里如果抛RuntimeException,则会导致所有相关事务回滚,个别事务传播机制有点特殊,我们下面会讲到。
事务方法里如果抛Throwable或者Exception,默认不会导致相关事务回滚,一般都会在出异常的地方提交,就有可能出现部分提交的问题。但可以配置rollback-for属性来控制。
1)REQUIRED
定义:如果有事务则加入事务,如果没有事务,则创建一个新的(默认值)
2)NOT_SUPPORTED
定义:Spring不为当前方法开启事务,相当于没有事务
NOT_SUPPORTED相当于没有Spring事务,每条执行语句单独执行,单独提交
3)REQUIRES_NEW
定义:不管是否存在事务,都创建一个新的事务,原来的方法挂起,新的方法执行完毕后,继续执行老的事务
REQUIRES_NEW为当前方法创建一个新的事务,并且当前事务先提交,然后再提交老的事务
4)MANDATORY
定义:必须在一个已有的事务中执行,否则报错
MANDATORY必须在已有事务下被调用,否则报错
5)NEVER
定义:必须在一个没有的事务中执行,否则报错
NEVER必须在没有事务的方法中执行,否则报错;
6)SUPPORTS
定义:如果其他bean调用这个方法时,其他bean声明了事务,则就用这个事务,如果没有声明事务,那就不用事务
SUPPORTS类型的事务传播机制,是否使用事务取决于调用方法是否有事务,如果有则直接用,如果没有则不使用事务
7)NESTED
定义:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与REQUIRED类似的操作
4.注意事项
1)REQUIRED
当两个方法的传播机制都是REQUIRED时,如果一旦发生回滚,两个方法都会回滚
2)REQUIRES_NEW
当delete方法传播机制为REQUIRES_NEW,会开启一个新的事务,并单独提交方法,所以save方法的回滚并不影响delete方法事务提交
3)NESTED
当save方法为REQUIRED,delete方法为NESTED时,delete方法开启一个嵌套事务;
当save方法回滚时,delete方法也会回滚;反之,如果delete方法回滚,则并不影响save方法的提交

TransactionTemplate…excute();//可以只管理中间的一段业务

public Object save2() {
   
        transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

        return transactionTemplate.execute(new TransactionCallback<Object>() {
   
            @Override
            public Object doInTransaction(TransactionStatus status) {
   
                // 新增用户
                User user = new User();
                user.setUsername("beta");
                user.setSalt(CommunityUtil.generateUUID().substring(0, 5));
                user.setPassword(CommunityUtil.md5("123" + user.getSalt()));
                user.setEmail("beta@qq.com");
                user.setHeaderUrl("http://image.nowcoder.com/head/999t.png");
                user.setCreateTime(new Date());
                userMapper.insertUser(user);

                // 新增帖子
                DiscussPost post = new DiscussPost();
                post.setUserId(user.getId())
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值