2016-09-18 39 views
0

我有一個問題,我接近解決方案或更好地說我接近如何避免問題EntityExistsException: A different object with the same identifier value但不明白什麼是真正的問題。爲了保持代碼簡短和集中,我做了一個小應用程序來模擬我的項目中的問題。Spring-Data JPA:EntityExistsException:具有相同標識符值的另一個對象

首先我有一個CrudRepository什麼保持總是相同的:

public interface EntityARepository extends CrudRepository<EntityA, Long> {} 

首先我得實體,其中一人有一個相對於其他:

@Entity 
@EqualsAndHashCode(of={"name"}) 
@ToString(of={"name"}) 
@XmlRootElement 
public class EntityA { 

    @Id 
    @GeneratedValue 
    @Setter 
    private Long id; 

    @Setter 
    @Column(nullable=false, unique=true) 
    private String name; 

    @Setter 
    @ManyToOne(fetch=EAGER, cascade={PERSIST, MERGE}) 
    private EntityB entityB; 

} 

@ToString(of = { "name" }) 
@EqualsAndHashCode(of = { "name" }) 
@Entity 
class EntityB { 
    @Id 
    // @GeneratedValue => produces issue! 
    @Setter 
    private Long id; 

    @Setter 
    @XmlAttribute 
    @Column(nullable=false, unique=true) 
    private String name; 
} 

然後我生成的數據和嘗試保存它們:

@Component 
public class DatabaseInitializer implements InitializingBean { 
    @Autowired EntityARepository repository; 

    @Override 
    public void afterPropertiesSet() throws Exception { 
     final Set<EntityA> aEntities = createAEntities(); 
     repository.save(aEntities); 
    } 

    private Set<EntityA> createAEntities() throws Exception { 
     Set<EntityA> aEntities = new HashSet<>(); 
     aEntities.add(getFirstEntityA()); 
     aEntities.add(getSecondEntityA()); 
     return aEntities; 
    } 

    private EntityA getFirstEntityA(){ 
     EntityA a = new EntityA(); 
     // a.setId(1L); 
     a.setName("a-1"); 
     a.setEntityB(getFirstEntityB()); 
     return a; 
    } 

    private EntityA getSecondEntityA(){ 
     EntityA a = new EntityA(); 
     // a.setId(2L); 
     a.setName("a-2"); 
     a.setEntityB(getFirstEntityB()); 
     return a; 
    } 

    private EntityB getFirstEntityB() { 
     EntityB b = new EntityB(); 
     b.setId(1l); 
     b.setName("b-1"); 
     return b; 
    } 
} 

有了這個構造,我變成了EntityExistsException

Caused by: javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [com.example.EntityB#1] 

回答

0

當firstEntityA被保存時,它也保存firstEntityB(因爲級聯)。因此,在該會話包含EntityB的實體後,其ID爲1.

當secondEntityA獲得持久性時,它還調用saveEventityB,然後引發異常。

原因是您無法調用保存在會話中已有ID的對象上。

有很多方法可以解決它。例如,你可以調用合併而不是保存。

repository.merge(aEntities); 

另一種方式來解決這個問題會做出EntityA的兩個實例有referene相同的EntityB對象:

private Set<EntityA> createAEntities() throws Exception { 
    Set<EntityA> aEntities = new HashSet<>(); 
    EntityB entityB = getFirstEntityB(); 
    aEntities.add(getFirstEntityA(entityB)); 
    aEntities.add(getSecondEntityA(entityB)); 
    return aEntities; 
} 

private EntityA getFirstEntityA(EntityB entityB){ 
    EntityA a = new EntityA(); 
    // a.setId(1L); 
    a.setName("a-1"); 
    a.setEntityB(entityB); 
    return a; 
} 

private EntityA getSecondEntityA(EntityB entityB){ 
    EntityA a = new EntityA(); 
    // a.setId(2L); 
    a.setName("a-2"); 
    a.setEntityB(entityB); 
    return a; 
} 

private EntityB getFirstEntityB() { 
    EntityB b = new EntityB(); 
    b.setId(1l); 
    b.setName("b-1"); 
    return b; 
} 
+0

謝謝您的回覆,我使用Spring的數據,它只是提供保存的方法。我猜測它會做出正確的邏輯。 –

+0

你可以試試這個另一個解決方案 - 我編輯了我的文章。 – mateuszlo

相關問題