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);