我正在使用 hibernate 作为我的持久层创建一个 CRUD API。
API 获取 JSON 并将其序列化为 POJO。然后管理层将 POJO 转换为新的 Hibernate 域对象。
Create
和 Update
都运行了完全相同的代码 - 唯一的区别是对于 Update
我还设置了 ID 字段 hibernate 对象。
创建工作正常,但更新失败并出现 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;
}
}
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)。
最佳答案
发生这种情况的唯一方法是您有两个数据库连接,它们都试图修改同一个实体。
如果单个用户发生这种情况,那是因为您没有对整个请求使用同一个 session ,而是创建了多个 session 。我会说你在某个外部级别打开一个 Hibernate session 和一个事务,当调用 update 方法时你打开另一个 session 和一个与可能已经获取的外部事务冲突的新事务锁定同一实体(因为您加载了该实体并对其进行了更改)。
关于java - 为什么我不能在没有 LockTimeoutException 的情况下合并()我的域对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31645457/