Answer the question
In order to leave comments, you need to log in
How to implement optimistic locking?
There is Spring + Hibernate + Mysql.
Implemented entity:
@Entity
@Table(name="Expenses")
public class Expense implements Serializable{
@Id
@Column(name="id_expense")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name="id_client", nullable=false)
private int idClient;
@Column(name="type_money", nullable=false)
private int typeMoney;
@Column(name="money")
private double money;
@Column(name="version")
@Version
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private int version;
@ManyToOne
@JoinColumn(name="id_client")
private Client client;
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
public int getIdClient(){
return idClient;
}
public void setIdClient(int idClient){
this.idClient = idClient;
}
public double getTypeMoney(){
return typeMoney;
}
public void setTypeMoney(int TypeMoney){
this.typeMoney = typeMoney;
}
public double getMoney(){
return money;
}
public void setMoney(double money){
this.money = money;
}
public Client getClient(){
return client;
}
public int getVersion(){
return version;
}
}
package com.ut.banking.dao.Expense;
import java.util.List;
import com.ut.banking.domain.Expense;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@Repository
public class ExpenseDAOdb implements ExpenseDAO {
@Autowired
private SessionFactory sessionFactory;
@Override
@Transactional
public List<Expense> listAll(int id){
return sessionFactory.getCurrentSession().createQuery("from Expense where idClient = :id").list();
}
@Override
@Transactional
public void add(Expense expense){
sessionFactory.getCurrentSession().save(expense);
}
@Override
@Transactional
public boolean remove(int id){
Expense expense = (Expense) sessionFactory.getCurrentSession().get(
Expense.class,
id,
new LockOptions(LockMode.PESSIMISTIC_WRITE)
);
if (expense == null) {
return false;
}
sessionFactory.getCurrentSession().delete(expense);
return true;
}
@Override
@Transactional
public boolean remove(Expense expense){
Expense newExpense = (Expense) sessionFactory.getCurrentSession().get(
Expense.class,
expense.getId(),
new LockOptions(LockMode.PESSIMISTIC_WRITE)
);
if (newExpense == null) {
return false;
}
sessionFactory.getCurrentSession().delete(expense);
return true;
}
@Override
@Transactional
public boolean withdraw(int id, int count){
Expense expense = (Expense) sessionFactory.getCurrentSession().get(
Expense.class,
id,
new LockOptions(LockMode.PESSIMISTIC_WRITE)
);
if (expense != null) {
return false;
}
double money = expense.getMoney();
if((money - count) > 0){
return false;
}
expense.setMoney(money);
return true;
}
@Override
@Transactional
public boolean withdraw(Expense expense, int count){
Expense newExpense = (Expense) sessionFactory.getCurrentSession().get(
Expense.class,
expense.getId(),
new LockOptions(LockMode.PESSIMISTIC_WRITE)
);
if (newExpense == null) {
return false;
}
double money = expense.getMoney();
if((money - count) > 0){
return false;
}
expense.setMoney(money);
return true;
}
@Override
@Transactional
public boolean topUp(int id, int count){
Expense expense = (Expense) sessionFactory.getCurrentSession().load(
Expense.class,
id,
new LockOptions(LockMode.PESSIMISTIC_WRITE)
);
if (expense != null) {
return false;
}
double money = expense.getMoney() + count;
expense.setMoney(money);
return true;
}
@Override
@Transactional
public boolean topUp(Expense expense, int count){
Expense newExpense = (Expense) sessionFactory.getCurrentSession().load(
Expense.class,
expense.getId(),
new LockOptions(LockMode.PESSIMISTIC_WRITE)
);
if (newExpense != null) {
return false;
}
double money = newExpense.getMoney() + count;
expense.setMoney(money);
return true;
}
}
package com.ut.banking.service.Expenses;
import java.util.List;
import com.ut.banking.dao.Expense.ExpenseDAO;
import com.ut.banking.domain.Client;
import com.ut.banking.domain.Expense;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ExpensesServiceDB implements ExpensesService {
@Autowired
ExpenseDAO expenseDAO;
@Override
public boolean add(Expense expense){
}
@Override
public boolean remove(Expense expense){
}
@Override
public boolean remove(int id){
}
@Override
public List<Expense> listAll(int idClient){
}
@Override
public boolean transfer(int idFrom, int idTo, Client client){
}
@Override
public boolean transger(int idFrom, int idTo, int idClient){
}
@Override
public boolean topUp(int id, Client client){
}
@Override
public boolean topUp(int id, int idClient){
}
@Override
public boolean withdraw(int id, Client client){
}
@Override
public boolean withdraw(int id, int idClient){
}
}
Answer the question
In order to leave comments, you need to log in
It is enough to have a field annotated with @Version like you have. In order to lock an entity, call the lock() method of the EntityManager, passing it the entity itself and the type of optimistic lock - for reading or writing: LockModeType.OPTIMISTIC or LockModeType.OPTIMISTIC_FORCE_INCREMENT.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question