我正在從資料庫中讀取一條記錄并更新它,我有兩種方法。但是在這兩個操作之間,我想獲得該特定行的鎖,以便不同的執行緒不會處理同一行。
這是我的存盤庫代碼:
package com.anco.crud.repository;
import com.anco.crud.model.Employee;
import org.hibernate.Session;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
@Repository
public class EmployeeRepositoryImpl implements EmployeeRepository{
@Autowired
private EntityManager entityManager;
@Override
@Transactional
public Employee findEmpToProcessAndUpdateStatus() {
Session currentSession = entityManager.unwrap(Session.class);
String hql = "from Employee where status is null";
Query query = currentSession.createQuery(hql);
query.setMaxResults(1);
Employee employee = (Employee) query.uniqueResult();
System.out.println("FETCHED : " employee.getFirstName());
employee.setStatus("INPROGRESS");
updateEmployee(employee);
return employee;
}
private boolean updateEmployee(Employee employee) {
try{
Thread.sleep(3000);
Session currentSession = entityManager.unwrap(Session.class);
currentSession.update(employee);
System.out.println("UPDATED : " employee.getFirstName());
}catch (Exception e){
e.printStackTrace();
}
return true;
}
}
控制器代碼:
@GetMapping("/employee/{mail}")
public boolean getAndUpdate() {
for(int i=0;i<5;i ){
Runnable rn = () -> process();
this.executor.execute(rn);
}
return true;
}
private void process() {
try {
Employee emp = employeeRepository.findEmpToProcessAndUpdateStatus();
} catch (Exception e) {
e.printStackTrace();
}
}
如果這不是正確的方法,那么什么是更好的方法?
uj5u.com熱心網友回復:
您可以設定特定的鎖定模式,以便向 DBMS 發出“選擇更新”:
EntityManager em;
...
Employee found = em.find(Employee.class, empId, LockModeType.PESSIMISTIC_WRITE);
uj5u.com熱心網友回復:
首先,充分利用 Spring,您目前正在解決它。您應該有一個單一的事務方法來完成這項作業。接下來只需使用 JPA 而不是直接訪問 Hibernate Session,它不會在這里增加任何混亂/復雜性。最后使用setLockModeon 查詢來確定鎖。
您的存盤庫方法(或服務)應如下所示
@Repository
public class EmployeeRepositoryImpl implements EmployeeRepository{
@PersistenceContext
private EntityManager em;
@Override
@Transactional
public Employee findEmpToProcessAndUpdateStatus() {
String hql = "SELECT e FROM Employee e where e.status is null";
TypedQuery<Employee> query = em.createQuery(hql, Employee.class);
query.setMaxResults(1);
query.setLockMode(LockModeType.PESSIMISTIC_WRITE);
Employee employee = query.getSingleResult();
System.out.println("FETCHED : " employee.getFirstName());
employee.setStatus("INPROGRESS");
this.updateEmployee(employee);
return employee;
}
private boolean updateEmployee(Employee employee) {
try{
Thread.sleep(3000);
em.merge(employee);
System.out.println("UPDATED : " employee.getFirstName());
}catch (Exception e){
e.printStackTrace();
}
return true;
}
}
但是,這可能會導致所有這些鎖導致資料庫死鎖。所以請謹慎使用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/382055.html
