java 如何在Hibernate和Sping Boot 中使用双向自引用级联创建和删除实体?

k5ifujac  于 2023-05-21  发布在  Java
关注(0)|答案(1)|浏览(137)

我尝试使用双向自引用级联创建和删除实体,但不起作用。

  • 当级联类型为ALL时-正在创建但不删除实体;
  • 当级联类型为REMOVE时-实体正在删除但不创建;
  • 不能使用fetch = Lazy,因为我需要在删除之前验证所有字段,而且无论如何我需要获取所有子字段;

使用Spring 3和PostgreSQL

实体:

@Entity
@Getter
@Setter
@Table(name = "field")
public class Field {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    @JdbcTypeCode(SqlTypes.BIGINT)
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToOne
    @JoinColumn(name = "parent_field_id")
    private Field parentField;

    @OneToMany(mappedBy = "parentField", fetch = FetchType.EAGER, cascade =  CascadeType., orphanRemoval = true)
    private Set<Field> childFields = new HashSet<>();

}

测试代码:

final Field firstLevel = createField("firstLevel");
final Field secondLevel = createField("secondLevel");
secondLevel.setParentField(firstLevel);
firstLevel.getChildFields().add(secondLevel);

final Field thirdLevel = createField("thirdLevel");
thirdLevel.setParentField(secondLevel);
secondLevel.getChildFields().add(thirdLevel);
fieldRepo.save(firstLevel);

// Checking child fields saved
final Field filedWithChild = fieldRepo.findById(1L).get();
filedWithChild.getChildFields().forEach(field -> Assert.isTrue(field.getId() != null));

// Trying to remove second level
log.info("Prepare to delete");
fieldRepo.deleteById(2L);
final Optional<Field> byId = fieldRepo.findById(2L);
Assert.isTrue(byId.isEmpty(),"Second level was not removed");

日志显示删除后没有sql delete请求本身

2023-05-19T10:56:55.109+05:00  INFO 31018 --- [  restartedMain] c.e.springbatchtest.app.SpringBatch      : Prepare to delete
2023-05-19T10:56:55.110+05:00 DEBUG 31018 --- [  restartedMain] org.hibernate.SQL                        : select f1_0.id,c1_0.parent_field_id,c1_0.id,c1_0.name,f1_0.name,p1_0.id,p1_0.name,p1_0.parent_field_id from field f1_0 left join field c1_0 on f1_0.id=c1_0.parent_field_id left join field p1_0 on p1_0.id=f1_0.parent_field_id where f1_0.id=?
Hibernate: select f1_0.id,c1_0.parent_field_id,c1_0.id,c1_0.name,f1_0.name,p1_0.id,p1_0.name,p1_0.parent_field_id from field f1_0 left join field c1_0 on f1_0.id=c1_0.parent_field_id left join field p1_0 on p1_0.id=f1_0.parent_field_id where f1_0.id=?
2023-05-19T10:56:55.112+05:00 DEBUG 31018 --- [  restartedMain] org.hibernate.SQL                        : select c1_0.parent_field_id,c1_0.id,c1_0.name from field c1_0 where c1_0.parent_field_id=?
Hibernate: select c1_0.parent_field_id,c1_0.id,c1_0.name from field c1_0 where c1_0.parent_field_id=?
2023-05-19T10:56:55.114+05:00 DEBUG 31018 --- [  restartedMain] org.hibernate.SQL                        : select c1_0.parent_field_id,c1_0.id,c1_0.name from field c1_0 where c1_0.parent_field_id=?
Hibernate: select c1_0.parent_field_id,c1_0.id,c1_0.name from field c1_0 where c1_0.parent_field_id=?
2023-05-19T10:56:55.120+05:00 DEBUG 31018 --- [  restartedMain] org.hibernate.SQL                        : select f1_0.id,c1_0.parent_field_id,c1_0.id,c1_0.name,f1_0.name,p1_0.id,p1_0.name,p1_0.parent_field_id from field f1_0 left join field c1_0 on f1_0.id=c1_0.parent_field_id left join field p1_0 on p1_0.id=f1_0.parent_field_id where f1_0.id=?
Hibernate: select f1_0.id,c1_0.parent_field_id,c1_0.id,c1_0.name,f1_0.name,p1_0.id,p1_0.name,p1_0.parent_field_id from field f1_0 left join field c1_0 on f1_0.id=c1_0.parent_field_id left join field p1_0 on p1_0.id=f1_0.parent_field_id where f1_0.id=?
2023-05-19T10:56:55.122+05:00 DEBUG 31018 --- [  restartedMain] org.hibernate.SQL                        : select c1_0.parent_field_id,c1_0.id,c1_0.name from field c1_0 where c1_0.parent_field_id=?
Hibernate: select c1_0.parent_field_id,c1_0.id,c1_0.name from field c1_0 where c1_0.parent_field_id=?
2023-05-19T10:56:55.124+05:00 DEBUG 31018 --- [  restartedMain] org.hibernate.SQL                        : select c1_0.parent_field_id,c1_0.id,c1_0.name from field c1_0 where c1_0.parent_field_id=?
Hibernate: select c1_0.parent_field_id,c1_0.id,c1_0.name from field c1_0 where c1_0.parent_field_id=?
gj3fmq9x

gj3fmq9x1#

由于您使用的是spring-boot,并且使用spring data https://spring.io/guides/gs/accessing-data-jpa/创建数据库功能相当简单,因此我建议创建一个特殊的'getByParentId'和/或'deleteByParentId',并从代码中单独调用方法。

相关问题