【Java】Spring事务相关笔记

Spring事务相关笔记

事务的四大特征

  • 原子性:事务中的全部操作在数据库中是不可分割的,要么全部执行,要么均不执行
  • 一致性:几个并行的事务,其执行结果必须与按某一顺序串行执行的结果相一致
  • 隔离性:事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须透明
  • 持久性:对于已提交的事务,系统必须保证该事务对数据库的改变不被丢失

事务使用

表结构示例:

drop table student;
create table `student`(
    `id` int unsigned auto_increment,
    `name` varchar(64),
    `age` int unsigned,
    primary key (`id`)
) engine=InnoDB default charset=utf8mb4;

实体类:

package com.alone.community.transaction.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

/**
 * @author Alone
 */
@Data
@Entity
public class Student {

    @Id
    @GeneratedValue
    private Integer id;

    private String name;

    private Integer age;

    public Student() {
    }

    public Student(Integer id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

dao:

@Repository
public interface StudentRepository extends JpaRepository<Student, Integer> {
}

service:

public interface StudentService {

    Student saveStudent(Student student);
}
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentRepository studentRepository;

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Student saveStudent(Student student) {
        Student save = studentRepository.save(student);
        if("Alone".equals(save.getName())) {
            throw new RuntimeException("Alone已存在!");
        }
        return save;
    }
}

controller:

@RestController
@RequestMapping("/student")
public class StudentController {

    @Autowired
    private StudentService studentService;

    @RequestMapping("/savestudent")
    public Student saveStudent(@RequestBody Student student) {
        return studentService.saveStudent(student);
    }
}

事务注解@Transactional的常见参数

参数作用
value当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器
transactionManager当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器
propagation事务的传播级别,默认值为Proppagation.REQUIRED
isolation事务的隔离级别,默认值为Isolation.DEFAULT
timeout事务超时时间,默认值为-1,如果超过该时间限制但事务还没有完成,则自动回滚事务
rollbackFor用于指定能够触发事务回滚的异常类型,可以指定多个异常类型

事务隔离级别

参数事务隔离级别脏读不可重复读幻读
READ_UNCOMMITTED读未提交(read-uncommitted)
READ_COMMITTED不可重复读(read-committed)
REPEATABLE_READ可重复读(repeatable-read)
SERIALIZABLE串行化(serializable))

事务传播级别

传播行为解释
REQUIRED如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务
SUPPORTS如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行
MANDATORY如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常
REQUIRES_NEW重新创建一个新的事务,如果当前存在事务,暂停当前的事务
NOT_SUPPORTED以非事务的方式运行,如果当前存在事务,暂停当前的事务
NEVER以非事务的方式运行,如果当前存在事务,则抛出异常
NESTED和REQUIRED效果一样

事务失效的场景

  1. 访问权限问题

spring要求被代理的方法必须是public的。
在源码的AbstractFallbackTransactionAttributeSource类的computeTransactionAttribute 方法中判断了,如果目标方法不是public,则TransactionAttribute 返回null。

@Nullable
    protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
        if (this.allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
            return null;
        } else {
            Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
            TransactionAttribute txAttr = this.findTransactionAttribute(specificMethod);
            if (txAttr != null) {
                return txAttr;
            } else {
                txAttr = this.findTransactionAttribute(specificMethod.getDeclaringClass());
                if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
                    return txAttr;
                } else {
                    if (specificMethod != method) {
                        txAttr = this.findTransactionAttribute(method);
                        if (txAttr != null) {
                            return txAttr;
                        }

                        txAttr = this.findTransactionAttribute(method.getDeclaringClass());
                        if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
                            return txAttr;
                        }
                    }

                    return null;
                }
            }
        }
    }
  1. 方法被final或static修饰
    spring内部是通过aop生成代理类来实现事务功能,如果某个方法用final或static修饰了,在代理类中就无法重写该方法,从而添加事务功能。

  2. 方法内部调用
    这篇文章中存在方法内部调用事务成功的情况,有待研究

方法内部调用不会生成代理对象,所以事务失效。如果想要调用,则需注入一下自己。

  1. 未被Spring管理
  2. 多线程调用

spring的事务是通过数据库连接来实现的,数据库连接又是通过ThreadLocal来保存的,多个线程同时调用时产生了多个ThreadLocal,则会有多个数据库连接。

  1. 表不支持事务
  2. 未开启事务
  3. 错误的事务传播级别
  4. 自己吞了异常
  5. 异常类型不正确

参考资料

  1. SpringBoot基础之声明式事务和切面事务和编程式事务
  2. SpringBoot 实战 (十) | 声明式事务
  3. 阿里P6都不一定全都答对,spring事务失效12种场景
### 更改CloudCompare中点云或模型的颜色 #### 设置背景颜色 为了更好地展示不同颜色的效果,在更改点云颜色之前可以先调整背景颜色。通过菜单栏中的`View -> Background color...`选项,可以选择不同的背景色彩[^2]。 #### 修改点云颜色 对于想要改变特定点云或者模型的颜色的情况: - 首先加载所需的点云文件并应用(`Apply`)操作以确保数据被正确读取[^3]。 - 接着在左侧的数据库树(DB Tree)面板里找到对应的点云条目,并单击选中它[^1]。 此时有几种方式来定义新的颜色属性: - **全局统一颜色**: 右键点击所选对象,在弹出菜单中选择`Change Color...`命令,这会打开一个小窗口允许指定RGB数值或是直接选取一种预设颜色。 - **基于属性的颜色映射**: 如果点云带有额外的信息(比如强度、分类标签),可以通过`Render -> Scalar field`路径下的子项来进行更复杂的视觉编码。例如,按照高程高度渐变显示,则应挑选`Z (height)`作为标量字段。 完成上述任一步骤之后,即可看到视窗内的点云外观发生了相应变化。如果希望保留这些修改以便日后查看,记得及时利用`File -> Save As`功能另存整个项目文件。 ```python # 这是一个示意性的Python脚本片段,实际CloudCompare并不支持此方法设置颜色;仅供理解逻辑流程参考 cloud.set_color(r=0, g=255, b=0) # 假定函数用于设定绿色 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值