I am trying to fetch records from Matrix table and update one record based on some logic inside a transaction. This transaction is triggered concurrently 5-6 times.
So using isolation level REPEATABLE_READ, it is expected that read and write locks are acquired on the rows once the transaction begins and locks are released after transaction commits. One transaction should acquire locks and other transactions should wait and then read the updated value by previous transaction.
This is the code of transaction:
public Matrix getAllocatedMatrix(Float score, ExamMode mode, String centre) {
if (Objects.isNull(score)) {
return null;
}
logger.info("Here 2");
logger.info("Here score: {}", score);
SessionFactory sessionFactory = getSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.getTransaction();
try {
logger.info("Here 3");
//start transaction
transaction.begin();
Criteria MatrixCr = session.createCriteria(Matrix.class);
MatrixCr.add(Restrictions.eq("mode", mode));
MatrixCr.addOrder(Order.desc("maxScorePercent"));
MatrixCr.add(Restrictions.eq("centre", centre));
logger.info("Here 4");
// fetch scholarship configs
List<Matrix> matrixList = runQuery(session, MatrixCr, Matrix.class);
Matrix allocatedMatrix = null;
for (Matrix matrix : matrixList) {
if (score < matrix.getMinScorePercent()) {
continue;
}
if (Objects.nonNull(matrix.getMaxStudentCount()) && matrix.getStudentsCount() < matrix.getMaxStudentCount()) {
allocatedMatrix = matrix;
break;
}
}
if (allocatedMatrix == null) {
allocatedMatrix = matrixList.get(matrixList.size() - 1);
}
logger.info("Here 5");
// update allocated scholarship config
String hqlUpdate = "update Matrix mat set mat.studentsCount = mat.studentsCount + 1, mat.lastUpdatedTime = :lastUpdatedTime where mat.id = :id";
session.createQuery(hqlUpdate)
.setString("id", allocatedMatrix.getId())
.setLong("lastUpdatedTime", System.currentTimeMillis())
.executeUpdate();
//commit the transaction
transaction.commit();
logger.info("Here 6");
return allocatedMatrix;
} catch (Exception ex) {
if (transaction.getStatus().equals(TransactionStatus.ACTIVE)) {
logger.error("Matrix Rollback: " + ex.getMessage());
session.getTransaction().rollback();
}
} finally {
logger.info("Here 7");
session.close();
}
return null;
}
The Matrix entity class:
public class Matrix {
@Id
private String id;
@Enumerated(EnumType.STRING)
private ExamMode mode;
private String centre;
private Float maxScorePercent;
private Float minScorePercent;
private Float discountPercent;
private Integer studentsCount = 0;
private Integer maxStudentCount;
}
I am setting isolation level using <property name="hibernate.connection.isolation">4</property> in hibernate config.
However, all transactions are reading the same value and not the updated value by previous transactions. What is the cause for this issue.
I am using hibernate version: 5.1.0.Final, cannot update this to latest version due to various factors.