Why can't I merge () my domain object without a LockTimeoutException?
I am creating a CRUD API using hibernate as my persistence layer.
The API takes JSON and serializes it to POJO. The management plane then transforms the POJO into a new Hibernate domain object.
This exact code runs for Create
as well as for Update
- the only difference is that for Update
I also set the hibernate object ID field.
Creation works fine, but Update fails org.hibernate.exception.LockTimeoutException
. After hours of surveillance around me, I'm going to wave a white flag and hope that someone can explain all the reasons I'm an idiot.
ClientManager code
public class ClientManager {
private static final ClientDAO clientDAO = new ClientDAO();
...
public Client updateClient(ClientVO inputVO) {
// Generate a Client from the input
Client client = ClientManager.generateClient(inputVO);
client.setClientKey(Integer.parseInt(inputVO.getPersonalId()));
client.setUpdateDate(new Date());
client.setUpdateTimestamp(new Date());
// Update the client
clientDAO.update(client);
}
...
public static Client generateClient(ClientVO clientVO) {
Client client = new Client();
client.setFirstName(clientVO.getFirstName());
client.setMiddleName(clientVO.getMiddleName());
client.setLastName(clientVO.getLastName());
return client;
}
}
BaseDAO code (CustomerDAO extends BaseDAO)
public class BaseDAO {
public Boolean save(Object object) {
Session session = getSession();
Transaction tx = session.beginTransaction();
session.save(object);
tx.commit();
session.close();
return Boolean.TRUE;
}
public Boolean update(Object object) {
Session session = getSession();
Transaction tx = session.beginTransaction();
session.merge(object);
tx.commit();
session.close();
return Boolean.TRUE;
}
public Session getSession()
{
return HibernateSessionFactory.getSession();
}
}
Entry point code
@PUT
@Path("clients/{personalId}")
@Produces({MediaType.APPLICATION_JSON})
public String updateClient(@PathParam("personalId") String personalId, String data) throws JsonParseException, JsonMappingException, IOException {
ClientVO inputVO = om.readValue(data, ClientVO.class);
inputVO.setPersonalId(personalId);
ClientVO outputVO = clientManager.updateClient(inputVO);
return om.writeValueAsString(outputVO);
}
Note that clientKey is the primary key.
The timeout occurs at a point .commit()
in the update () method of BaseDAO.
I'm happy to provide more code (like ClientVO) if helpful.
source to share
The only way it can happen is if you have two database connections trying to modify the same object.
If this happens to a single user, it is because you are not using the same session for the entire request, but instead you are creating multiple. I would say that you open a Hibernate session and transaction on some external level, and when the update method is called, you open another session and a new transaction that conflicts with the external one, which might already have acquired locks on the same object ( because you loaded the object and changed it).
source to share