gene b.
gene b.

Reputation: 11974

org.hibernate.UnsupportedLockAttemptException: Lock mode not supported : Hibernate 4->5 Upgrade

We've just upgraded Hibernate 4->5 in our application. The following code used to work in Hibernate 4. There is a job which fetches some data from MAIL_HISTORY_T and can optionally write into MAIL_HISTORY_T as well in the same transaction.

@Transactional(readOnly = false)
@Scheduled(cron = "${mail.cron.reviewer.task.reminder}") 
public void sendPendingReviewerTaskRemainderEmail() {
    //...
    for(Reviewers reviewer: pendingTasks) {
        // Read from MAIL_HISTORY_T
        MailHistory mh = mailHistoryDAO.getMailHistoryByReqId(reviewer.getReqId()); 
        //...
        if (someCondition) {
            // Write to MAIL_HISTORY_T
            mailHistoryDAO.createNewMailHistory(reviewer.getReqId(), params); 
        }
    }
}

Error:

org.hibernate.UnsupportedLockAttemptException: Lock mode not supported
    at org.hibernate.engine.internal.ImmutableEntityEntry.setLockMode(ImmutableEntityEntry.java:128) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
    at org.hibernate.event.internal.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:220) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
    at org.hibernate.event.internal.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:52) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
    at org.hibernate.internal.SessionImpl.fireRefresh(SessionImpl.java:1295) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
    at org.hibernate.internal.SessionImpl.refresh(SessionImpl.java:1247) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final]
    at app.mcs.dao.MailHistoryDAO.persist(MailHistoryDAO.java:40) ~[classes/:]

Both the Read and Write operations on MAIL_HISTORY_T reference the same Request ID.

Any thoughts?

Upvotes: 0

Views: 540

Answers (2)

gene b.
gene b.

Reputation: 11974

We fixed this by rewriting the Write operation as Native SQL. The Read operation remains unchanged as before.

Therefore, the previous Hibernate-based createNewMailHistory() is now Native SQL:

    sessionFactory.getCurrentSession().createNativeQuery("insert "
            + "    into "
            + "        MAIL_HISTORY_T "
            + "        (ID, MAIL_TEMPLATE_ID, MAIL_IDENTIFIER, REQUEST_ID, SYSTEM_COMMENTS, CREATED_DATE, CREATED_BY) "
            + "    values "
            + "        (nextval('mh_seq'), :mailTemplateId, :mailIdentifier, :requestId, :systemComments, :createdDate, :createdBy)")
        .setParameter("mailTemplateId", mailTemplateDAO.findByShortIdentifier(mailIdentifier).getId())
        .setParameter("mailIdentifier", mailIdentifier)
        .setParameter("requestId", req.getId())
        .setParameter("systemComments", systemComments)
        .setParameter("createdDate", new Date())
        .setParameter("createdBy", null)
        .executeUpdate();
}

Upvotes: 1

Ashish Patil
Ashish Patil

Reputation: 4604

Somehow your code is creating ImmutableEntityEntry which is new introduction in Hibernate 5.

As per ImmutableEntityEntry code, it only support LockMode.NONE & LockMode.READ (see ImmutableEntityEntry#setLockMode method).

Your code is reading & updating same entity so it is most likely hibernate is setting LockMode as LockMode.PESSIMISTIC_WRITE which is not supported by ImmutableEntityEntry.

Can you please check which AbstractEntityEntry instance you were receiving prior to Hibernate 5 update.

Edit :- There already exists a bug in hibernate regarding this https://hibernate.atlassian.net/browse/HHH-13601.

Currently,I am not sure how you can obtain MutableEntityEntry in your case which will help you to change your entity.

Upvotes: 1

Related Questions