Jpa一对多关系的删除 从表数据没有被删除
今天,在学习jpa是遇到一个问题,就是删除从表数据时,控制台打印了两次查询操作的sql语句,就和纳闷,明明调用的是deleteById方法,不应该先打印查询语句,然后才是删除语句。下面详细说说这个问题:
主表与从表的区分
简单一点的区分方式是:
主表:不含外键字段的表
从表:含有外键字段的表
我做的这个练习,主表是班级表:
@Getter
@Setter
@Entity(name = "t_clazz")
public class Clazz {//new Clazz
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int cid;
@Column
private String cname;
//表示一对多 表示一个班级有多个学生对象
@OneToMany(mappedBy = "clz",fetch = FetchType.EAGER,cascade = CascadeType.ALL)//mapperBy 创建一和多的映射关系,值是对方的属性名称
private List<Student> list;
}
从表是学生表:
@Getter
@Setter
@ToString
@Entity(name = "t_student")//外键表,子表
public class Student {//new Student
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer sid;
@Column
private String sname;
//表示多对一 多个学生对象属于同一个班级
@ManyToOne
@JoinColumn(name="cid")//指定了外键列:外键列没有指定name属性,默认名称clz
private Clazz clz;
}
删除学生表中的数据
@Test
public void deleteStudent(){
//删除学生信息,不用考虑cid的值,直接删除就ok
// Student student = new Student();
// student.setSid(10);
// studentDao.delete(student);
//删除没有成功,受到立即加载的影响
studentDao.deleteById(12);
}
执行这个测试类,控制台打印的sql语句:
Hibernate: select student0_.sid as sid1_1_0_, student0_.cid as cid3_1_0_, student0_.sname as sname2_1_0_, clazz1_.cid as cid1_0_1_, clazz1_.cname as cname2_0_1_ from t_student student0_ left outer join t_clazz clazz1_ on student0_.cid=clazz1_.cid where student0_.sid=?
Hibernate: select list0_.cid as cid3_1_0_, list0_.sid as sid1_1_0_, list0_.sid as sid1_1_1_, list0_.cid as cid3_1_1_, list0_.sname as sname2_1_1_ from t_student list0_ where list0_.cid=?
原因
删除没有成功,是因为fetch = FetchType.EAGER,这个是立即加载,只要查询学生信息也会查询学生的班级信息
@OneToMany(mappedBy = "clz",fetch = FetchType.EAGER,cascade = CascadeType.ALL)
解决方法
方法一:
将@OneToMany中的fetche改为懒加载,即fetch = FetchType.LAZY
@OneToMany(mappedBy = "clz",fetch = FetchType.LAZY,cascade = CascadeType.ALL)
方法二:
将@ManyToOne中的fetche改为懒加载,即fetch = FetchType.LAZY
@ManyToOne(mappedBy = "list",fetch = FetchType.LAZY,cascade = CascadeType.ALL)
注意:
@OneToMany--中默认加载方式是懒加载,即 FetchType.LAZY
@ManyToOne--中默认加载方式是立即加载,即 FetchType.EAGER
改完之后,控制台打印的sql语句如下:
Hibernate: select student0_.sid as sid1_1_0_, student0_.cid as cid3_1_0_, student0_.sname as sname2_1_0_, clazz1_.cid as cid1_0_1_, clazz1_.cname as cname2_0_1_ from t_student student0_ left outer join t_clazz clazz1_ on student0_.cid=clazz1_.cid where student0_.sid=?
Hibernate: delete from t_student where sid=?