Java 为什么可以';t I merge()我的域对象没有LockTimeoutException?
我正在使用hibernate作为持久层创建CRUDAPI API接受JSON并将其序列化为POJO。然后,管理层将POJO转换为新的Hibernate域对象 对于Java 为什么可以';t I merge()我的域对象没有LockTimeoutException?,java,hibernate,orm,concurrency,transactions,Java,Hibernate,Orm,Concurrency,Transactions,我正在使用hibernate作为持久层创建CRUDAPI API接受JSON并将其序列化为POJO。然后,管理层将POJO转换为新的Hibernate域对象 对于Create和Update运行的代码完全相同-唯一的区别是对于Update我还设置了hibernate对象的ID字段 创建工作正常,但更新失败,出现org.hibernate.exception.LockTimeoutException。经过几个小时的窥探,我要挥舞白旗,希望有人能解释我是白痴的所有原因 客户端管理器代码 public
Create
和Update
运行的代码完全相同-唯一的区别是对于Update
我还设置了hibernate对象的ID字段
创建工作正常,但更新失败,出现org.hibernate.exception.LockTimeoutException
。经过几个小时的窥探,我要挥舞白旗,希望有人能解释我是白痴的所有原因
客户端管理器代码
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;
}
}
@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);
}
BaseDAO代码(ClientDAO扩展BaseDAO)
入口点代码
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;
}
}
@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)。实现这一点的唯一方法是,您有两个数据库连接,它们都试图修改相同的实体
如果这种情况发生在单个用户身上,那是因为您没有对整个请求使用相同的会话,而是创建了多个会话。我想说的是,您在某个外部级别打开了一个Hibernate会话和一个事务,当调用update方法时,您打开了另一个会话和一个新事务,该会话和事务与可能已在同一实体上获取锁的外部会话和事务冲突(因为您加载了该实体并对其进行了更改).这是一个非常有用的思路——我只是通过收紧我的会话来确保我
.close()
正确地完成它们,但遗憾的是,这个问题仍然存在。我会继续挖掘,以防我遗漏了什么,并且我正在更新问题以显示入口点。我有理由相信我在这一点上没有包装事务——是否有可能Hibernate正在做奇怪的事情,因为我正在手动设置原始域对象的主键,而不是“查找”对象?我还通过手动设置实体标识符以及来自DTO的其他属性来更新实体。这是导致您出现问题的数据库锁。您是否使用一些触发器来获取其他表中其他数据库行的锁?没有触发器,模式非常简单,定义如下:| |我将继续挖掘,并在了解更多信息后报告。很好地理解了我所做的并不是天生违反了关于hibernate的某些东西。