我正在使用hibernate作为我的持久层创建一个CRUD API。
API采用JSON并将其序列化为POJO。然后管理层将POJO转换为新的Hibernate Domain对象。
对于Create
和Update
运行完全相同的代码 - 唯一的区别是对于Update
我还设置了hibernate对象的ID字段。
创建工作正常,但更新失败并显示org.hibernate.exception.LockTimeoutException
。经过几个小时的窥探,我将挥动白旗,希望有人能解释我是白痴的所有原因。
ClientManager代码
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代码(ClientDAO扩展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();
}
}
入口点代码
@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);
}
请注意,clientKey是主键。
超时发生在BaseDAO的update()方法中.commit()
处。
如果有用,我很乐意提供更多代码(例如ClientVO)。
答案 0 :(得分:4)
这种情况发生的唯一方法是你有两个数据库连接,它们都试图修改同一个实体。
如果单用户发生这种情况,那是因为您不对整个请求使用相同的Session,而是创建多个请求。我会说你在一些外层打开Hibernate Session和一个事务,当调用 update 方法时,你打开另一个Session和一个新的事务,它与可能已经获得的外部事务冲突锁定在同一个实体上(因为你加载了实体并对其进行了更改)。