简体   繁体   中英

java.lang.IllegalStateException: Multiple representations of the same entity [] are being merged. Detached: []; Detached: []

I have three entities EntityA, EntityB and EntityC as follows:

EntityA:

import lombok.*;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table(name = "Entity_A")
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = "locationA")
@ToString(of = "locationA")
public class EntityA {
    @Id
    @Column(name = "Name_A", length = 10)
    private String nameA;
    @Column(name = "Loc_A", length = 10)
    private String locationA;
    @ManyToMany(cascade = { CascadeType.MERGE })
    @JoinTable(
            name = "En_A_On_B",
            joinColumns = { @JoinColumn(name = "Name_A") },
            inverseJoinColumns = { @JoinColumn(name = "B_id") }
    )
    private Set<EntityB> bs;
}

EntityB:

import lombok.*;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table(name = "Entity_B")
@Setter
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = "locationB")
@ToString(of = "locationB")
public class EntityB {
    @Id
    @GeneratedValue
    @Column(name = "B_id")
    private int id;
    @Column(name = "Loc_B", length = 10)
    private String locationB;
    @ManyToMany(cascade = { CascadeType.MERGE })
    @JoinTable(
            name = "En_C_on_B",
            joinColumns = { @JoinColumn(name = "B_id") },
            inverseJoinColumns = { @JoinColumn(name = "C") }
    )
    private Set<EntityC> cs;
 }

EntityC:

 import lombok.*;

import javax.persistence.*;
import java.util.Set;

@Entity
@Table(name = "Entity_C")
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = "c")
@ToString(of = "c")
public class EntityC {
    @Id
    @Column(name = "C", length = 20)
    private String c;    
}

SERVICE CLASS TO SAVE:

@Service
@Slf4j
public class ServiceClass {
    @Autowired
    private EntityARepository entityARepository;

    private Set<EntityC> cs1 = new HashSet<>(asList(
            EntityC.builder().c("100").build(),
            EntityC.builder().c("10").build()
    ));

    private Set<EntityC> cs2 = new HashSet<>(asList(
            EntityC.builder().c("100").build(),
            EntityC.builder().c("200").build()
    ));

    //METHOD TO SAVE
    public void save() {
        Map<String, Set<EntityC>> map = new HashMap<>();
        map.put("B1", cs1);
        map.put("B2", cs2);

        List<String> bs = asList("B1", "B2");
        EntityA aa = EntityA.builder().nameA("abcd").locationA("mon").build();
        EntityA ab = EntityA.builder().nameA("abcde").locationA("money").build();

        bs.forEach(b -> {
            EntityB entityB = EntityB.builder().locationB("100xxx").build()
            entityB.getCs().addAll(map.get(b));            

            aa.getBs().add(entityB);
            ab.getBs().add(entityB);
        });

        entityARepository.save(aa);
        entityARepository.save(ab);
    }
}

Execution of above code throws following exception

Caused by: java.lang.IllegalStateException: Multiple representations of the same entity [com.xxx.xxx.xxx.xxx.EntityC#100] are being merged. Detached: [(c=100)]; Detached: [(c=100)]

Note: I have explored on the internet but none of them matcches with my scenario

Any idea how can I rectify the issue

The problem is right here:

private Set<EntityC> cs1 = new HashSet<>(asList(
        EntityC.builder().c("100").build(), //this entity instance has the same identifier...
        EntityC.builder().c("10").build()
));

private Set<EntityC> cs2 = new HashSet<>(asList(
        EntityC.builder().c("100").build(), //...as this one
        EntityC.builder().c("200").build()
));

You are trying to persist two versions of the same entity, in a single unit of work. Imagine you put:

EntityC.builder().c("100").name("A name").build()

in cs1 and:

EntityC.builder().c("100").name("Another name").build()

in cs2 instead. Since both entities have the same id ( c="100" ), how is Hibernate supposed to know which version 'wins'?

Try putting the same instance of EntityC in both sets and the problem should go away.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM