hibernate UnuniqueObjectException:具有相同标识符值的不同对象已与会话关联:

hibernate UnuniqueObjectException:具有相同标识符值的不同对象已与会话关联:,hibernate,hibernate-mapping,Hibernate,Hibernate Mapping,我的代码: 我正在尝试执行更新/插入。它被正确插入,唯一的问题是当我试图更新它时,它会给出下面的错误消息 private String sessionType=null; public String getAccountsDetails(List<Account> accountList) { Session session = sessionFactory.openSession(); for (Account account : accountLis

我的代码:

我正在尝试执行更新/插入。它被正确插入,唯一的问题是当我试图更新它时,它会给出下面的错误消息

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";
}

编辑2:

我用过

会话.合并(accountDetails)


没有错误,但它总是将数据插入数据库,而不是更新。

按照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";
}
私有字符串sessionType=null;
公共字符串getAccountsDetails(列表accountList){
Session Session=sessionFactory.openSession();
for(帐户:accountList){
AccountDetails AccountDetails=新的AccountDetails();
accountDetails.setAccountsId(Long.parseLong(account.getId());
accountDetails.setAccounttype(account.getAccountType().value());
Query Query=session.createQuery(“来自QBAccounts qba,其中qba.accountsId=:accId”);
List queryList=query.setParameter(“accId”,accountDetails.getAccountsId()).List();
如果(queryList.size()>0){
更新(账户详情);
sessionType=“更新”;
}否则{
session.save(accountDetails);
sessionType=“保存”;
}
}
session.flush();
session.beginTransaction().commit();
session.clear();
session.close();
返回“数据成功更新到表中”;
}
公共字符串getAccountsDetails(AccountDetails AccountDetails){
System.out.println(“accountDetails.accountId-->”+accountDetails.getAccountsId());
Session Session=sessionFactory.openSession();
Query Query=session.createQuery(“来自QBAccounts qba,其中qba.accountsId=:accId”);

List

回复很晚,但是其他正在搜索相同错误的人可以知道。这对我来说很有效。在提交前使用session.flush()和提交后使用session.clear()在循环中保存数据时


我在开始两次会议时犯了这个错误。 一个会话用于用户,另一个会话用于主键为用户外键的对象。 这样,两个会话具有相同的主键或标识符。 我通过session.clear before session.update(type)解决了此问题

公共T更新(T类型){
Session=getSession();
session.clear();
更新(类型);
session.flush();
返回类型;

}

您的帐户详细信息实体的主键是什么?是AccountsId吗

您已将帐户详细信息从数据库提取到当前的hibernate会话

    Query query = session.createQuery("from QBAccounts qba where qba.accountsId=:accId");
    List<AccountDetails> queryList = query.setParameter("accId", accountDetails.getAccountsId()).list();
accountDetails从暂时状态传递到持久状态,然后由当前会话管理,但由于之前获取了accounts详细信息,您的会话中已经有一个ID相同的对象,所以hibernate会话变得混乱


当您使用“合并”时,hibernate会将现有会话内对象的状态与新对象accountDetails同步。

为什么要使用两个不同的会话?您可以在同一会话中处理保存和更新,除非我遗漏了一些内容。请看这是否有帮助@lalit,我尝试了同一个会话,正如我所告知的,它在同一会话中工作第一次使用ne进行插入,然后下一步是更新,它会引发相同的错误。之前我遇到了过时的对象状态异常,所以我使用了不同的会话。上面已更新。可能重复我在同一会话中尝试过的,正如我所知,第一次使用insert可以正常工作,然后下一步是更新,它会引发相同的错误。之前我是g正在设置过时的对象状态异常,因此我使用了不同的会话。指向artricle的链接已失效
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";
    }
    session.flush();
    session.beginTransaction().commit();
    session.clear();
    Query query = session.createQuery("from QBAccounts qba where qba.accountsId=:accId");
    List<AccountDetails> queryList = query.setParameter("accId", accountDetails.getAccountsId()).list();
    session.save(accountDetails);