(注意:已编辑以添加代码以重现行为)
我有以下三个实体
@Entity
public class ClassA {
@Id private UUID id = UUIDGenerator.generate();
@OneToMany(mappedBy = "classA", cascade = {CascadeType.PERSIST, CascadeType.DETACH,CascadeType.REMOVE}, orphanRemoval = true)
List<ClassB> classBs= new ArrayList<>();
//setters and getters
}
@Entity
public class ClassB {
@Id private UUID id = UUIDGenerator.generate();
@OneToOne(cascade = {CascadeType.PERSIST, CascadeType.DETACH, CascadeType.REMOVE},
orphanRemoval = true, mappedBy = "classB")
private ClassC classC;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "classA_id")
private ClassA classA;
// setters and getters
@Entity
public class ClassC {
@Id private UUID id = UUIDGenerator.generate();
@OneToOne //(fetch = FetchType.LAZY)
@MapsId
private ClassB classB;
//setters and getters
}
public interface ClassARepository extends CrudRepository<ClassA, UUID> {}
//Example code to reproduce
ClassC classC_1 = new ClassC();
ClassC classC_2 = new ClassC();
ClassB classB_1 = new ClassB();
ClassB classB_2 = new ClassB();
classC_1.setClassB(classB_1);
classC_2.setClassB(classB_2);
classB_1.setClassC(classC_1);
classB_2.setClassC(classC_2);
ClassA classA = new ClassA();
classB_1.setClassA(classA);
classB_2.setClassA(classA);
classA.getClassBs().add(classB_1);
classA.getClassBs().add(classB_2);
classARepository.save(classA);
我正在使用Spring Boot和CRUD存储库。第一次尝试保存类型A的实体时,我希望由于有了CascadeType.PERSIST
批注,将保存类A,B和C的所有层次结构。但是事实并非如此,我回来了
org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find classB with id ...
如果我将@OneToMany
级联类型更改为CascadeType.ALL
,则将保存classA和classB,但不保存classC。如果我将所有层叠类型更改为ALL,则将保存所有内容。
但是,我只想在创建新实体时而不是在合并时级联保存操作,我认为这正是PERSIST的意思。有人可以解释上述行为,我如何实现自己想要的?
致谢
答案 0 :(得分:0)
我正在回答自己的问题:
似乎问题出在id生成策略上。在这种情况下,我在存储在存储库中之前会生成ID,这会引起麻烦。具体地
据我所见SimpleJpaRepository
拥有此代码
public <S extends T> S save(S entity) {
if (this.entityInformation.isNew(entity)) {
this.em.persist(entity);
return entity;
} else {
return this.em.merge(entity);
}
}
此处是JpaPersistableEntityInformation
实体是否为新实体的决定
public boolean isNew(T entity) {
return entity.isNew();
}
和entity.isNew()
的定义如下:
@Transient
public boolean isNew() {
return null == this.getId();
}
因此,换句话说,id生成策略实际上会影响级联的结果。实际上,我通过将id都更改为
来验证了我的假设@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
瞧,一切正常。
这不是理想的情况,但至少我知道为什么会这样。那么,PERSIST基本上仅适用于数据库生成的ID?似乎很奇怪,所以如果有人对如何解决此问题有任何建议,请告诉我们。
致谢