当涉及到企业应用程序时,正确地管理对数据库的并发访问是相当重要的。为此,咱们可使用Java Persistence API提供的乐观锁定机制。它致使在同一时间对同一数据进行屡次更新不会相互干扰。为了使用OptimisticLocking,咱们须要一个实体(Entity),其中包含一个带有@Version注释的属性。在使用它时,每一个读取数据的事务都持有version属性的值。在事务想要进行更新以前,它将再次检查version属性。若是值在此期间发生了更改,则抛出ObjectOptimisticLockingFailureException。不然,事务提交update并递增version的值。这种机制适用于读操做比更新或删除操做多得多的应用程序。java
@Entity
@Table(name = "user")
@Data
@OptimisticLocking
public class User {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Integer id;
@Column(name = "username", unique = true, nullable = true, length = 50)
private String username;
private String password;
@Version
private Integer version;
@PrePersist
public void prePersist() {
version = 0;
}
}
复制代码
spring data jpa在上一篇文章已经作过一些讲解了【快学springboot】7.使用Spring Boot Jpa。感兴趣的朋友能够看看。这里定义了一个version字段,使用了Version注解标识。PrePersist这个注解表示在新增数据以前执行。spring
public interface UserRepo extends PagingAndSortingRepository<User, Integer>, JpaSpecificationExecutor<User> {
}
复制代码
public class UserTest extends SpringbootApplicationTests {
}
复制代码
SpringbootApplicationTests这个类是使用Spring initialize新建项目的时候自动生成的用来作单元测试的类。在UserTest上注入UserRepo,而且写一个新增user的单测。数据库
执行以后查看数据库。springboot
该记录已经被建立出来了。bash
执行后查看数据库:并发
能够看到version字段自增了1。app
新建一个方法,以下单元测试
这里查询了两次id为1的记录,而后分别更新了这条记录。根据前面的描述,这里会抛出一个ObjectOptimisticLockingFailureException异常。启动测试,结果以下:测试
这是符合预期的。看下数据库的version,在这种状况下,咱们的预期结果是version变为2。spa
经过数据库的值查看,测试都是符合预期的。
咱们把User实体的OptimisticLocking注解去掉,而后再次执行上面的方法。
这一次程序顺利执行了,而后查看下数据库的记录:
预期应该是version会变为3,而后username变为happyjava-new2。
经过结果来看,这是符合预期的。
spring data jpa经过OptimisticLocking实现了乐观锁,该乐观锁不是经过数据库自身去实现的,它是经过version字段(须要Version注解标识)去实现的。若是update的数据时候,发现数据库的version大于等于当前的version,则会抛出ObjectOptimisticLockingFailureException,错误信息是
Row was updated or deleted by another transaction
复制代码