Jpa org.springframework.dao.DataIntegrityViolationException:具有相同标识符值的不同对象已与会话关联

Jpa org.springframework.dao.DataIntegrityViolationException:具有相同标识符值的不同对象已与会话关联,jpa,session,transactions,Jpa,Session,Transactions,此方法从事务开始 @Transactional(propagation = Propagation.REQUIRED) public Account generateDirectCustomerAccountEntity(AccountReq source, Map<String, String> headers, String workflowId) { Account dbAccount = dCustomerModelToEntityMapper.map(source,

此方法从事务开始

@Transactional(propagation = Propagation.REQUIRED)
public Account generateDirectCustomerAccountEntity(AccountReq source, Map<String, String> headers, String workflowId) {
    Account dbAccount = dCustomerModelToEntityMapper.map(source, headers);
    dbAccount = saveAccount(source, dbAccount, headers, workflowId);
    return dbAccount;
}   
异常堆栈跟踪

错误Throwable={},“stack_trace”:“org.springframework.dao.DataIntegrityViolationException:具有相同标识符值的不同对象已与会话关联:[com.adobe.costheta.account.model.db.mysql.account#100000080];嵌套异常为javax.persistence.EntityExistsException:具有相同标识符值的不同对象已与会话关联:[com.adobe.costheta.account.model.db.mysql.account#100000080]\n\tat org.springframework.orm.jpa.EntityManagerFactoryUtils.ConvertJPAAccessException如果可能(EntityManagerFactoryUtils.java:400)\n\tat org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateException如果可能(HibernateJpaDialect.java:256)\n\tat org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:537)\n\tat org.springframework.transaction.support AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746)\n\t org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714)\n\t org.springframework.transaction.interceptor.TransactionSpectSupport.commitTransactionAfterReturning(TransactionSpectSupport.java:534)\n\tat org.springframework.transaction.interceptor.TransactionSpectSupport.invokeWithinTransaction(TransactionSpectSupport.java:305)\n\tat org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)\n\tat org.springframework.aop.framework.ReflectiveMethodInvoking.Proced(ReflectiveMethodInvocation.java:186)\n\tat org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.procement(ReflectiveMethodInvocation.java:186)\n\tat org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)\n\tat com.adobe.costheta.service.DbService$$EnhancerBySpringCGLIB$$8d6d52b1.generateDirectCustomerAccountity()\n\tat com.adobe.costheta.service.DirectCustomerAccountServiceImpl.createDirectCustomerAccount(DirectCustomerAccountServiceImpl.java:158)\n\tat com.adobe.costheta.service.DirectCustomerAccountServiceImpl$$FastClassBySpringCGLIB$$27f4a473.invoke()\n\tat org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\n\tat org.springframework.ao.aop.framework.CglibAopProxy$CglibAopProxy.invokeJoinpoint(cglobaopproxy.java:750)\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.procedue(ReflectiveMethodInvocation.java:163)\n\tat org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceduce(ReflectiveMethodInvocation.java:186)\n\tat org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)\n\tat com.adobe.costheta.service.DirectCustomerAccountServiceImpl$$EnhancerBySpringCGLIB$$13af2ff1.createDirectCustomerAccount()\n\tat com.adobe.costheta.resource.AccountResource.createAccount(AccountResource.java:93)\n\tat com.adobe.costheta.resource.AccountResource$$FastClassBySpringCGLIB$$dd5cfc46.invoke()\n\tat org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\n\tat org.springframework.aop.framework.CglibAopProxy$cglibMethodInvokeJoinPoint(CglibAopProxy.java:750)\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.procedue(ReflectiveMethodInvocation.java:163)\n\tat org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.procedue(MethodInvocationProceedingJoinPoint.java:88)\n\tat com.adobe.asr.logging.aspect.ExecutionTimeAspect.ExecutionTimeAspect.logExecutionTime(ExecutionTimeAspect\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(本机方法)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n\tat java.base/java.lang.reflect.reflect(Method.java:566)\n\tat org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)\n\tat org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)\n\tat org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.procedue(ReflectiveMethodInvocation.java:175)\n\tat org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceduce(ReflectiveMethodInvocation.java:186)\n\tat org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)\n\tat com.adobe.costheta.resource.AccountResource$$EnhancerBySpringCGLIB$$d988334a.createAccount()\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(本机方法)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n\tat java.base/java.lang.reflect.Method.invoke(Method.java:566)\n\tat org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)\n\tat org.springframework.web.servlet.mvc.method.annotation.servletineinvocablehandlermethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)\n\t org.springfra
@Override
@LogExecutionTime(log=true)
public Account map(AccountReq accountReq, Map<String, String> headers) {
        logger.info("AccountModelToEntityMapper.mapDirectCustomer*****START");
        Account dbAccount = new Account();
        AccountCode accountCode = dbService.getAccountCodeForDirectCustomer(accountReq);
        String accountId = dbService.genarateAccountId(accountCode);
        logger.info("genarated AccountID for Direct Customer is={}", accountId);
        dbAccount.setAccountId(accountId);
        setAccountContact(dbAccount, accountReq, headers);
        setAddress(dbAccount, accountReq);
        dbAccount.setAccountType(accountCode.getCodeId());
        return dbAccount;
}
private void setAccountContact(Account dbAccount, AccountReq accountReq, Map<String, String> headers) {

    try {
        if (null != accountReq.getContacts() && !accountReq.getContacts().isEmpty()) {
            logger.info("setAccountContact accountReq.getContacts().size()={}", accountReq.getContacts().size());
            List<String> emailList=new ArrayList<>();
            for (ContactReq contact : accountReq.getContacts()) {
                String email = contact.getEmail();
                logger.info("setAccountContact:"+email);
                if(emailList.contains(email)) {
                    logger.error("ERROR={}", "same emailId sent in multiple contacts");
                    throw new AccountException(AccountConstant.INVALID_FIELDS, AccountConstant.INVALID_FIELDS_CODE);
                
                }
                emailList.add(email);
                Contact dbcontact = contactRepository.findByEmail(email);
                if (null == dbcontact) {
                    dbcontact = new Contact();
                    dbcontact.setCreatedAt(dbAccount.getCreatedAt());
                    dbcontact.setCreatedBy(dbAccount.getCreatedBy());
                    dbcontact.setEmail(contact.getEmail());
                    dbcontact.setFirstName((contact.getFirstName()));
                    dbcontact.setLastName((contact.getLastName()));
                    dbcontact.setPhone(contact.getPhoneNumber());
                    dbcontact.setStatus(AccountConstant.STATUS_ACTIVE);
                    logger.info("contactRepository={} {}", contactRepository,contact.getEmail());

                    try {
                        dbcontact = contactRepository.save(dbcontact);
                    } catch (Exception e) {

                        logger.error("ERROR in updating contact table={}", e);
                        throw new InternalServerException(AccountConstant.INTERNAL_SERVER_ERROR,
                                AccountConstant.INTERNAL_SERVER_ERROR_CODE);
                    }
                }


                AccountContact dbAccountContact = new AccountContact();
                dbAccountContact.setCreatedAt(dbAccount.getCreatedAt());
                dbAccountContact.setCreatedBy(dbAccount.getCreatedBy());
                dbAccountContact.setStatus(AccountConstant.STATUS_ACTIVE);
                ContactRole contactRole = getContactRole(contact.getType());
                if (null == contactRole) {
                    logger.error("ERROR={}", "contact type is invalid");
                    throw new AccountException(AccountConstant.INVALID_FIELDS, AccountConstant.INVALID_FIELDS_CODE);
                }
                dbAccountContact.setContactRole(contactRole);
                dbAccountContact.setAccount(dbAccount);
                dbAccountContact.setContact(dbcontact);
                if (null != dbcontact.getAccountContact() && !dbcontact.getAccountContact().isEmpty()) {

                    logger.error("dbcontact.getAccountContact() is not null, dbcontact.getAccountContact().size()={}",
                            dbcontact.getAccountContact().size());  

                    List<AccountContact> accountContactList = dbcontact.getAccountContact();
                    accountContactList.add(dbAccountContact);
                } else {
                    logger.error("getAccountStatusHistory is null");
                    List<AccountContact> accountContactList = new ArrayList<>();
                    accountContactList.add(dbAccountContact);
                    dbcontact.setAccountContact(accountContactList);
                }
                
            
                    if (null != contact && AccountConstant.ADMIN_CONTACT_ROLE.equalsIgnoreCase(contact.getType())) {
                        if (null != contact.getAdminId()) {
                            dbService.saveExternalID(String.valueOf(dbcontact.getContactId()), contact.getAdminId(), headers, AccountConstant.STATUS_ACTIVE,
                                    CosConstants.ID_TYPE);
                        }
                    }
                

            }
        }
    } catch (Exception e) {
        logger.error("ERROR in setAccountContact to dbAccount contacts={},{}", accountReq.getContacts(), e);
        throw e;
    }
}

@LogExecutionTime(log = true)
public Account saveDirectCustomerAccount(AccountReq source, Account dbAccount, Map<String, String> headers, String workflowId) {
    
        try {
            String statusCode=AccountConstant.INITIAL_STATUS_CODE;
            dbAccount = updateAccountStatusHistory(dbAccount, statusCode);

        } catch (Exception e) {

            logger.error("ERROR in updateAccountStatusHistory={}", e);
            throw new InternalServerException(AccountConstant.INTERNAL_SERVER_ERROR,
                    AccountConstant.INTERNAL_SERVER_ERROR_CODE);
        }

        return dbAccount;
    }

@LogExecutionTime(log = true)
private Account updateAccountStatusHistory(Account dbAccount, String statusCode) {

    logger.info("updateAccountStatusHistory *****START");
    AccountStatusHistory accountStatusHistory = new AccountStatusHistory();
    accountStatusHistory.setAccount(dbAccount);
    accountStatusHistory.setCreatedAt(dbAccount.getCreatedAt());
    accountStatusHistory.setCreatedBy(dbAccount.getCreatedBy());
    try {
        updateAccountStatus(dbAccount, statusCode, accountStatusHistory);
    } catch (Exception e) {

        logger.error("ERROR updateAccountStatus e={}", e);
    }

    if (null != dbAccount.getAccountStatusHistory()) {

        logger.error("getAccountStatusHistory not null");
        dbAccount.getAccountStatusHistory().add(accountStatusHistory);

    } else {
        logger.error("getAccountStatusHistory is null");
        List<AccountStatusHistory> accountStatusHistoryList = new ArrayList<>();
        accountStatusHistoryList.add(accountStatusHistory);
        dbAccount.setAccountStatusHistory(accountStatusHistoryList);
    }

    Account createdAccount = saveAccount(dbAccount);
    logger.debug("createdAccount.getAccountId()={}", createdAccount.getAccountId());
    return createdAccount;

}
public Account saveAccount(Account dbAccount) {
    try {

        Account createdAccount = accountRepository.save(dbAccount);
        logger.debug("createdAccount.getAccountId()={}", createdAccount.getAccountId());
        return createdAccount;
    } catch (Exception e) {

        logger.error("ERROR in account creation={}", e);
        throw new InternalServerException(AccountConstant.INTERNAL_SERVER_ERROR,
                AccountConstant.INTERNAL_SERVER_ERROR_CODE);
    }
}
Account dbAccount = new Account(); //Account A created
dbService.genarateAccountId(accountCode);
dbAccount = accountRepository.save(dbAccount); //Account A passed to `save`, `save` returns Account B, Account A is not referenced anywhere anymore, problem solved
Contact dbcontact = contactRepository.findByEmail(email);
@QueryHints(value = { @QueryHint(name = org.hibernate.annotations.QueryHints.FLUSH_MODE, value = "COMMIT") }) //  this prevents a flush before querying
Contact findByEmail(String email);