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.

+3


source to share


1 answer


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).

+4


source







All Articles