我尝试使用双向自引用级联创建和删除实体,但不起作用。
- 当级联类型为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=?
1条答案
按热度按时间gj3fmq9x1#
由于您使用的是spring-boot,并且使用spring data https://spring.io/guides/gs/accessing-data-jpa/创建数据库功能相当简单,因此我建议创建一个特殊的'getByParentId'和/或'deleteByParentId',并从代码中单独调用方法。