java.lang.IllegalStateException:正在合并同一实体[]的多个表示形式。分离:[];分离:[]
我有三个实体EntityA、EntityB和EntityC,如下所示: 实体A: 要保存的服务类:java.lang.IllegalStateException:正在合并同一实体[]的多个表示形式。分离:[];分离:[],java,hibernate,jpa,many-to-many,Java,Hibernate,Jpa,Many To Many,我有三个实体EntityA、EntityB和EntityC,如下所示: 实体A: 要保存的服务类: @Service @Slf4j public class ServiceClass { @Autowired private EntityARepository entityARepository; private Set<EntityC> cs1 = new HashSet<>(asList( EntityC.builde
@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);
}
}
执行上述代码会引发以下异常
原因:java.lang.IllegalStateException:正在合并同一实体[com.xxx.xxx.xxx.xxx.EntityC100]的多个表示形式。分离:[c=100];分离:[c=100]
注:我已经在互联网上进行了探索,但没有一个与我的场景相符
你知道我该如何纠正这个问题吗?问题就在这里:
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()
));
在cs1和:
而是在cs2中。既然两个实体都具有相同的id c=100,那么Hibernate如何知道哪个版本“获胜”
尝试将EntityC的同一实例放在两个集合中,问题就会消失 您是否尝试过像about CascadeType.MERGE:那样更改级联类型?您的Spring Boot和H2数据库代码运行得很好。我使用的是mssql。它正在为我引发异常。将CascadeType.MERGE更改为CascadeType.ALL,看看发生了什么。它引发了相同的异常它不会是实际场景中的同一个实例,而是两个不同的解组实例。我正在使用equals和hashCode方法。那么,恐怕同样的问题仍然存在。无论从何处获取实体,如果尝试使用相同的ID合并不同的实体实例,Hibernate无法自行决定哪个版本是正确的。您需要强制引用相等,否则它将不起作用。如果要保存EntityB和EntityC之间的关联,而不是保存整个未签名的EntityC状态,则需要使用repository.getOne获取对预先存在的EntityC的引用,并使用该实例而不是map.getb;在entityB.getCs.addAll中。。。Line使用Spring Boot和H2数据库时,操作代码工作正常。@EugenCovaci是否将调用包装以保存到事务中?如果不是,则entityARepository.saveaa和entityARepository.saveab会创建两个单独的事务,因此问题不会出现surface@crizzis无论entityARepository.save是否标记为@Transactional,它都能正常工作。顺便说一句,创建或不创建EntityArepositional.save transactional不会创建两个事务。
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
@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);
}
}
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()
));
EntityC.builder().c("100").name("A name").build()
EntityC.builder().c("100").name("Another name").build()