[Spring] 27. Using JPA to implement optimistic locks @ Version annotation, jpa @ version
When the persistence layer uses jpa, an annotation @ Version is provided by default to implement optimistic locks.
Simply put, a version field is used to act as an optimistic lock.
Design entity classes first
/** * Created by xujingfeng on 2017/1/30. */@Entity@Table(name = "t_student")public class Student { @Id @GenericGenerator(name = "PKUUID", strategy = "uuid2") @GeneratedValue(generator = "PKUUID") @Column(length = 36) private String id; @Version private int version; private String name; //getter()... //setter()...}
Dao Layer
/** * Created by xujingfeng on 2017/1/30. */public interface StudentDao extends JpaRepository<Student,String>{ @Query("update Student set name=?1 where id=?2") @Modifying @Transactional int updateNameById(String name,String id);}
The Controller layer acts as a unit test, and calls a requestMapping to trigger the method we want to test.
/** * Created by xujingfeng on 2017/1/30. */@Controllerpublic class StudentController { @Autowired StudentDao studentDao; @RequestMapping("student.html") @ResponseBody public String student(){ Student student = new Student(); student.setName("xujingfeng"); studentDao.save(student); return "student"; } @RequestMapping("testVersion.html") @ResponseBody public String testVersion() throws InterruptedException { Student student = studentDao.findOne("6ed16acc-61df-4a66-add9-d17c88b69755"); student.setName("xuxuan"); new Thread(new Runnable() { @Override public void run() { studentDao.findOne("6ed16acc-61df-4a66-add9-d17c88b69755"); student.setName("xuxuanInThread"); studentDao.save(student); } }).start(); Thread.sleep(1000); studentDao.save(student); return "testVersion"; } @RequestMapping("updateNameById.html") @ResponseBody public String updateNameById(){ studentDao.updateNameById("xuxuan2","6ed16acc-61df-4a66-add9-d17c88b69755"); return "updateNameById"; }}
The three methods here are mainly the three points of attention we want to use for testing.
The first example student.html is to see how springdata increases the version field. If you do not need to map the image, you can directly draw a conclusion. For the Annotation with @ Version added, you do not need to manually control the image. Each save operation is based on + 1. If the initial value is null, springdata is automatically set to 0.
The second example testversion.html is the core of optimistic locks. What kind of control will the program perform after @ Version optimistic locks are added when multiple threads concurrently access the same row of records?
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.example.jpa.Student#6ed16acc-61df-4a66-add9-d17c88b69755]
The exception information is as above. The master thread and the new thread obtain the same row record, and the new thread first commits the transaction. The version number is consistent and the modification is successful. When the main thread wants to save and commit the transaction, it will get an exception with inconsistent version numbers. in project development, you should capture this exception and handle it based on the business content, retry or discard etc...
In the third example, updatenamebyid.html wants to emphasize that the update and delete operations in @ Query do not trigger spring data-related proxy operations, but convert them to native SQL, so pay attention to this point when using it in projects.
Summary
Optimistic locks are used in some sensitive business data, and their modification: Optimism indicates that the version is consistent in most scenarios. However, from the business point of view, it is necessary to ensure strict data consistency to avoid dirty reading and other problems. Use cases should be considered. I remember the previous blog briefly introduced the concept of Row-level locks. In fact, both in essence and optimistic locks are intended to lock and control concurrency at the database level. When should we use optimistic locks and row-level locks, when must I add synchronization locks at the program level and determine based on specific business scenarios. Finding a solution that meets your project needs and finding a balance between performance and reliability is the value of a programmer.
Source: http://www.importnew.com/26099.html