我的代码:
我正在尝试更新/插入。它被正确地插入,唯一的问题是当我试图更新它时,它会给出下面的错误消息。
private String sessionType=null;
public String getAccountsDetails(List<Account> accountList) {
Session session = sessionFactory.openSession();
for (Account account : accountList) {
AccountDetails accountDetails = new AccountDetails();
accountDetails.setAccountsId(Long.parseLong(account.getId()));
accountDetails.setAccounttype(account.getAccountType().value());
Query query = session.createQuery("from QBAccounts qba where qba.accountsId=:accId");
List<AccountDetails> queryList = query.setParameter("accId", accountDetails.getAccountsId()).list();
if(queryList.size()>0){
session.update(accountDetails);
}else{
session.save(accountDetails);
}
}
session.flush();
session.beginTransaction().commit();
session.clear();
session.close();
return "Successfully data updated into table";
}
错误:
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.trinet.mulesoft.quickbooks.dto.AccountDetails#0]
at org.hibernate.engine.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:638)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:305)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:246)
编辑2:
我用过
session.mmerge(accountDetails)
没有错误,但它总是将数据插入数据库,而不是更新。
我在打开两个会话时出现了这个错误。一个会话用于用户,另一个会话则用于主键为来自用户的外键的对象。这样,两个会话就具有相同的主键或标识符。我通过session.clear before session.update(type).解决了这个问题
public T update(T type) {
Session session = getSession();
session.clear();
session.update( type );
session.flush();
return type;
}
public String getAccountsDetails(AccountDetails accountDetails) {
System.out.println("accountDetails.accoundId-->"+accountDetails.getAccountsId());
Session session = sessionFactory.openSession();
Query query = session.createQuery("from QBAccounts qba where qba.accountsId=:accId");
List<AccountDetails> queryList = query.setParameter("accId", accountDetails.getAccountsId()).list();
session.close();
Session session2 = sessionFactory.openSession();
// session.saveOrUpdate(accountDetails);
try{
if(queryList.size()>0){
session2.beginTransaction();
/*
* comment below line-50,51 to use update instead of merge, and uncomment line 53
*/
AccountDetails acDet = (AccountDetails) session2.get(AccountDetails.class, new Long(1));//line 50
session2.merge(accountDetails);//line 51
System.out.println("acDet-->"+acDet+" --accountDetails-> "+accountDetails);//line 52
// session2.update(accountDetails);//line 53
}else{
session2.beginTransaction();
session2.save(accountDetails);
}
}catch(DIRException e){
session2.getTransaction().rollback();
System.out.println("Getting Exception : " + e.getLocalizedMessage());
}finally{
session2.getTransaction().commit();
session2.close();
}
return "Successfully data updated into table";
}
从我的dto中删除了@GeneratedValue,因为值来自UI。
这是一篇很好的文章,如何使用MERGE/UPDATE
按照lalit的建议,尝试只使用一个会话。
代码缩减为如下。
private String sessionType=null;
public String getAccountsDetails(List<Account> accountList) {
Session session = sessionFactory.openSession();
for (Account account : accountList) {
AccountDetails accountDetails = new AccountDetails();
accountDetails.setAccountsId(Long.parseLong(account.getId()));
accountDetails.setAccounttype(account.getAccountType().value());
Query query = session.createQuery("from QBAccounts qba where qba.accountsId=:accId");
List<AccountDetails> queryList = query.setParameter("accId", accountDetails.getAccountsId()).list();
if(queryList.size()>0){
session.update(accountDetails);
sessionType = "update";
}else{
session.save(accountDetails);
sessionType = "save";
}
}
session.flush();
session.beginTransaction().commit();
session.clear();
session.close();
return "Successfully data updated into table";
}
回复很晚,但其他正在搜索相同错误的人可以知道。这对我很有效。当你在提交之前将数据保存在循环中时,请使用session.flush()和提交之后使用session.clear().
session.flush();
session.beginTransaction().commit();
session.clear();
您的Account Details实体的PK是什么?是AccountsId吗?
您已将数据库中的帐户详细信息提取到当前休眠会话中。
Query query = session.createQuery("from QBAccounts qba where qba.accountsId=:accId");
List<AccountDetails> queryList = query.setParameter("accId", accountDetails.getAccountsId()).list();
保存时
session.save(accountDetails);
accountDetails从暂时状态传递到持久状态,然后由当前会话管理,但由于之前获取了帐户详细信息,您的会话中已经有一个具有相同ID的对象,因此hibernate会话变得混乱。
当您使用merge时,hibernate会将会话中现有对象的状态与您的新对象accountDetails同步。