2017-01-02 359 views
0

通過SO搜索,但我無法找到我的情況。JPA - OneToMany persist - EntityExistsException

有實體卡,像這樣:

import javax.persistence.CascadeType; 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.ForeignKey; 
import javax.persistence.Id; 
import javax.persistence.Index; 
import javax.persistence.JoinColumn; 
import javax.persistence.JoinTable; 
import javax.persistence.ManyToMany; 
import javax.persistence.ManyToOne; 
import javax.persistence.OneToMany; 
import javax.persistence.Table; 

import lombok.AccessLevel; 
import lombok.Getter; 
import lombok.Setter; 
import lombok.ToString; 

import org.hibernate.validator.constraints.NotBlank; 
import org.hibernate.validator.constraints.NotEmpty; 

@Entity 
@ToString(exclude={"playRequirements"}) 
@Table(name = "CARD", 
     indexes = {@Index(name = "CARD_IDX_1", columnList="ID", unique = true)}) 
public class Card implements Serializable { 

    @Getter 
    @Setter 
    @NotEmpty 
    @NotBlank 
    @Id 
    @Column(name = "ID", unique = true, nullable = false) 
    private String id; 

    @Getter 
    @Setter 
    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="card") 
    private List<CardPlayRequirementsRel> playRequirements; 
} 

,作爲與實體CardPlayRequirementsRel的反比關係:

import java.io.Serializable; 

import hscli.entities.domain.PlayRequirement; 

import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.ForeignKey; 
import javax.persistence.Id; 
import javax.persistence.Index; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 
import javax.persistence.Table; 

import lombok.EqualsAndHashCode; 
import lombok.Getter; 
import lombok.Setter; 
import lombok.ToString; 

import org.hibernate.validator.constraints.NotEmpty; 

@Entity 
@ToString 
@EqualsAndHashCode(of={"card", "playRequirement"}) 
@Table(name = "CARD_PLAY_REQUIREMENT_REL", 
     [email protected](name="CARD_PLAY_REQ_REL_IDX_1", unique=true, columnList="CARD,PLAY_REQUIREMENT")) 
public class CardPlayRequirementsRel implements Serializable { 

    @Id 
    @Getter 
    @Setter 
    @NotEmpty 
    @ManyToOne(fetch = FetchType.EAGER) 
    @JoinColumn(name = "CARD", nullable = false, foreignKey = @ForeignKey(name = "FK_CARD_PLAY_REQ_REL_CARD")) 
    private Card card; 

    @Id 
    @Getter 
    @Setter 
    @NotEmpty 
    @ManyToOne(fetch = FetchType.EAGER) 
    @JoinColumn(name = "PLAY_REQUIREMENT", nullable = false, foreignKey = @ForeignKey(name = "FK_CARD_PLAY_REQ_REL_PLAY_REQ")) 
    private PlayRequirement playRequirement; 

    @Getter 
    @Setter 
    @NotEmpty 
    @Column(name = "VALUE", nullable = false) 
    private Long value; 
} 

我要堅持卡的列表:

[...] 

List<CardDTO> dtoList = connectionService.getCardDTO(); 
List<Card> toSave = new ArrayList<Card>(); 
for(CardDTO dto : dtoList) { 
    log.debug("----------------> id: [" + dto.getId() + "]"); 
    Card entity = new Card(); 
    dtoToCardEntity(dto, entity); 
    toSave.add(entity); 
} 
cardRepository.save(toSave); 

[...] 

private void dtoToCardEntity(CardDTO dto, Card entity) { 
    entity.setId(dto.getId()); 

    if(dto.getPlayRequirements() != null && CollectionUtils.isNotEmpty(dto.getPlayRequirements().keySet())) { 
     entity.setPlayRequirements(new ArrayList<CardPlayRequirementsRel>()); 
     for(String playReq : dto.getPlayRequirements().keySet()) { 
      CardPlayRequirementsRel rel = new CardPlayRequirementsRel(); 
      rel.setCard(entity); 
      rel.setPlayRequirement(domainBaseService.findOneByCodice(playReq, PlayRequirement.class)); 
      rel.setValue(dto.getPlayRequirements().get(playReq)); 
      entity.getPlayRequirements().add(rel); 
     } 
    } 
} 

但保存我得到這個例外:

13398 02:04:41,679 [main] DEBUG [org.hibernate.SQL:92] - 
    select 
     cardplayre0_.PLAY_REQUIREMENT as PLAY_REQUIREMENT2_7_0_, 
     cardplayre0_.CARD as CARD3_7_0_, 
     cardplayre0_.VALUE as VALUE1_7_0_ 
    from 
     CARD_PLAY_REQUIREMENT_REL cardplayre0_ 
    where 
     cardplayre0_.PLAY_REQUIREMENT=? 
     and cardplayre0_.CARD=? 
13398 02:04:41,679 [main] TRACE [org.hibernate.type.descriptor.sql.BasicBinder:65] - binding parameter [1] as [VARCHAR] - [REQ_MINION_TARGET] 
13399 02:04:41,680 [main] TRACE [org.hibernate.type.descriptor.sql.BasicBinder:65] - binding parameter [2] as [VARCHAR] - [AT_024] 
13404 02:04:41,685 [main] ERROR [hscli.HearthStoneCardListImporter:56] - A different object with the same identifier value was already associated with the session : [hscli.entities.cards.CardPlayRequirementsRel#CardPlayRequirementsRel(card=null, playRequirement=null, value=0)]; nested exception is javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [hscli.entities.cards.CardPlayRequirementsRel#CardPlayRequirementsRel(card=null, playRequirement=null, value=0)] 
org.springframework.dao.DataIntegrityViolationException: A different object with the same identifier value was already associated with the session : [hscli.entities.cards.CardPlayRequirementsRel#CardPlayRequirementsRel(card=null, playRequirement=null, value=0)]; nested exception is javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [hscli.entities.cards.CardPlayRequirementsRel#CardPlayRequirementsRel(card=null, playRequirement=null, value=0)] 
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:410) 
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:246) 
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:491) 
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) 
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) 
    at com.sun.proxy.$Proxy41.save(Unknown Source) 
    at hscli.services.impl.CardServiceImpl.updateCards(CardServiceImpl.java:52) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) 
    at com.sun.proxy.$Proxy44.updateCards(Unknown Source) 
    at hscli.HearthStoneCardListImporter.updateCards(HearthStoneCardListImporter.java:54) 
    at hscli.HearthStoneCardListImporter.main(HearthStoneCardListImporter.java:29) 
Caused by: javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [hscli.entities.cards.CardPlayRequirementsRel#CardPlayRequirementsRel(card=null, playRequirement=null, value=0)] 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1664) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1608) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:1171) 
    at sun.reflect.GeneratedMethodAccessor36.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298) 
    at com.sun.proxy.$Proxy39.merge(Unknown Source) 
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:509) 
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:540) 
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:72) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:503) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:488) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:460) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) 
    ... 23 more 
+0

您是否已驗證CardPlayRequirementsRel實例的兩個PK字段是否爲空? –

回答

0

如果您的實體中有多個列注有@Id,則必須使用@IdClass註釋或將其替換爲嵌入@EmbeddedId。看到How to map a composite key with Hibernate?的一個很好的解釋,這似乎是獨立於休眠。

我不完全確定這實際上是你現在看到的問題,因爲異常似乎抱怨ID字段爲null的多個實例,所以既然你沒有指定任何生成器,你應該確保id列被設置爲實際值並且不爲null。

+0

非常感謝。 使用'@ EmbeddedId'註解解決。 – Otrebor79