2016-09-18 35 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

相关问题