【Hibernate学习笔记】7:单向1-N关联和双向1-N关联,其中的Lazy Loading(懒加载)
程序员文章站
2022-04-22 16:10:57
...
单向1-N关联
如果在Teacher的POJO中组合了所有该老师带的Student对象,而在Student的属性中没有他所属的Teacher,这种情况就是单向1-N关联,即从1的一方去维护所有的相关的N。
在教师的POJO类添加
// 新增的该老师所带的全部学生,设定HashSet的初始容量是0
private Set<Student> set_stu = new HashSet<Student>(0);
// 有参构造器,新增这个学生集合
public Teacher(String tchrNo, String tchrName, Integer mny, Set<Student> stu) {
this.tchrNo = tchrNo;
this.tchrName = tchrName;
this.mny = mny;
this.set_stu = stu;// 新增
}
//对它所组合的Student集合生成getter和setter
public Set<Student> getSet_stu() {
return set_stu;
}
public void setSet_stu(Set<Student> set_stu) {
this.set_stu = set_stu;
}
在学生的POJO类修改
注释掉组合了所属Teacher的属性和相关的方法,在单向1-N关联中不允许N方的对象能直接获取所关联的1方。
// private Teacher tchr;
// 有参构造器,去掉这一参数
public Student(String stuNo, String stuName, Date dtIn/* , Teacher tchr */) {
this.stuName = stuName;
this.stuNo = stuNo;
this.dtIn = dtIn;
// this.tchr = tchr;
}
// 注释掉原Teacher属性的getter和setter
// public Teacher getTchr() {
// return tchr;
// }
//
// public void setTchr(Teacher tchr) {
// this.tchr = tchr;
// }
更改教师的映射文件
注意只要是1-N关联都是N方外键引用1方主键,数据库中表的结构还是和上篇生成的一样的。只是关联的方向不同,显示在面向对象层面的维护方式不同。
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="myPOJO">
<class name="Teacher" table="TeacherTable">
<id name="id" column="ID" type="int">
<generator class="native" />
</id>
<property name="tchrNo" column="TCHRNO" type="string" not-null="true" />
<property name="tchrName" type="string" not-null="true">
<column name="TCHRNAME" />
</property>
<property name="mny" column="MONEY" type="int" not-null="false" />
<!--新增单向1-N关联中1方的集合属性,指出属性名-->
<set name="set_stu">
<!--指出N方表中外键的字段名,只要是1-N关联都是N方外键引用1方主键-->
<key column="TEACHER_ID"/>
<!--指出所维护的N方所在的POJO类-->
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>
更改学生的映射文件
注释掉上篇配置的N-1映射。
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="myPOJO">
<class name="Student" table="StudentTable">
<id name="id" column="ID" type="int">
<generator class="native" />
</id>
<property name="stuNo" column="STUNO" type="string" not-null="true" />
<property name="stuName" type="string" not-null="true">
<column name="STUNAME" />
</property>
<property name="dtIn" column="DATEIN" type="date" not-null="true" />
<!-- <many-to-one name="tchr" column="TEACHER_ID" class="Teacher" not-null="false" cascade="all"/> -->
</class>
</hibernate-mapping>
在主类中测试
因为Hibernate的懒加载策略,当不确定会使用这种需要额外查询才能获得的PO中组合的N方的集合时,并不会去加载它。如果提前关闭了Session,如在下面中的第18行或者第23行,将没有办法依靠1-N关联从1方中获取N方的集合。
import java.util.Set;
import myPOJO.Student;
import myPOJO.Teacher;
import myTools.HibernateUtils;
import org.hibernate.Session;
//测试学生到班主任的N-1关系映射
public class Main {
// 主方法
public static void main(String[] args) {
// 根据逻辑主键id来获取一个教师PO
System.out.println("根据逻辑主键id来获取一个教师PO");
Session sssn = HibernateUtils.getSession();
Teacher tchr = (Teacher) sssn.get(Teacher.class, 1);
// HibernateUtils.closeSession();
// 因为存在单向1-N映射,从这个教师PO中可以获取其所有学生
System.out.println("因为存在单向1-N映射,从这个教师PO中可以获取其所有学生");
Set<Student> set_stu_from_tchr = tchr.getSet_stu();
// HibernateUtils.closeSession();
System.out.println(tchr.getTchrName() + "的学生有这些:");
System.out.println("逻辑主键\t学号\t姓名\t入学时间");
for (Student s : set_stu_from_tchr) {
System.out.println(s.getId() + "\t" + s.getStuNo() + "\t"
+ s.getStuName() + "\t" + s.getDtIn());
}
// 因为Hibernate的懒加载,在单向1-N中不去主动getN方的集合时并不会去从数据库中读到PO里
HibernateUtils.closeSession();
}
}
运行结果
根据逻辑主键id来获取一个教师PO
Hibernate: select teacher0_.ID as ID1_1_0_, teacher0_.TCHRNO as TCHRNO2_1_0_, teacher0_.TCHRNAME as TCHRNAME3_1_0_, teacher0_.MONEY as MONEY4_1_0_ from TeacherTable teacher0_ where teacher0_.ID=?
因为存在单向1-N映射,从这个教师PO中可以获取其所有学生
大司马的学生有这些:
逻辑主键 学号 姓名 入学时间
Hibernate: select set_stu0_.TEACHER_ID as TEACHER_5_1_0_, set_stu0_.ID as ID1_0_0_, set_stu0_.ID as ID1_0_1_, set_stu0_.STUNO as STUNO2_0_1_, set_stu0_.STUNAME as STUNAME3_0_1_, set_stu0_.DATEIN as DATEIN4_0_1_ from StudentTable set_stu0_ where set_stu0_.TEACHER_ID=?
2 S0002 刘傻逼 2018-04-20
1 S0001 刘知昊 2018-04-20
双向1-N关联
双向1-N关联就是双向N-1关联,只要再将前面对N方POJO及其映射文件的注释解除就可以实现,即单向1-N和单向N-1共同使用。
尽量使用双向1-N关联而不是单向1-N关联。因为懒加载的存在,双向1-N关联比单向N-1关联带来的代价不高。