Jpa一对多关系的删除 数据删除失败

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=?
上一篇:学习笔记-MySQL


下一篇:Docker In Action 学习笔记 根据第二版有所更新