PS:禁止拷贝形式转载,转载请以URL形式
1.简介
解决JPA/hibernate 实体多对多关系下,操作实体无法直接级联删除中间表,报错。
2.环境
- jdk1.8
- springboot:2.2.8.RELEASE
3.解决思路
-
正常多对多
- 实体A使用多对多关联(@ManyToMany)关联B,JPA自动生成第三张中间表C,
- 然后在需要删除实体并且级联删除中间表时,提前删除中间表C的关联数据。
-
双向一对多
- 实体A使用双向一对多(@OneToMany)关联C,并且设置C为维护方;
- 实体B使用双向一对多(@OneToMany)关联C,并且设置C为维护方;
- 通过JPA任意删除A/B都会删除中间表数据C,而不会删除另一方
4.代码
4.1 双向一对多实现
实体A
@Data
@Entity
@Table(name = "tb_a")
public class TbA {
@Id
@Column(name = "c_uuid", unique = true, length = 36, nullable = false)
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "org.hibernate.id.UUIDGenerator")
private String uuid;
@OneToMany(cascade = {CascadeType.ALL},mappedBy = "a")
private List<TbC> cList;
}
实体B
@Data
@Entity
@Table(name = "tb_b")
public class TbB {
@Id
@Column(name = "c_uuid", unique = true, length = 36, nullable = false)
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "org.hibernate.id.UUIDGenerator")
private String uuid;
@OneToMany(cascade = {CascadeType.ALL},mappedBy = "b")
private List<TbC> cList;
}
中间表C
@Data
@Entity
@Table(name = "tb_c")
@IdClass(TbC.TbCEmbeddable.class)
public class TbC {
@Id
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH})
@JoinColumn(name = "c_a_foreign_key")
private TbA a;
@Id
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH})
@JoinColumn(name = "c_b_foreign_key")
private TbA b;
@Data
public static class TbCEmbeddable implements Serializable {
private TbA a;
private TbB b;
}
}
级联删除代码
@NoRepositoryBean
public interface BaseDao<T,ID extends Serializable> extends JpaRepository<T,ID> , JpaSpecificationExecutor<T> {
//RestResource
}
BaseDao<TbCollectManageItem,String> dao = factory.getDao(TbCollectManageItem.class);
dao.deleteById(uuid);