本章代码:https://github.com/MarsOu1998/OneToMany
一对多关联:one-to-many
题目:班级和学生是一对多的关系,要求实现:对班级的信息进行查询的时候,无需另外查询就可以获得学生的信息。
数据库如下,因为class这个词比较容易冲突,所以换成Banji:
步骤:
- 建立POJO Banji.java,Student.java,建立Hibernate配置文件,将两个hbm文件与其绑定
- 在Banji.java里面建立一个Set类型的属性,准备装学生。
- 在Banji的hbm文件中添加
<set name="set属性名称" table="对应的另一个表的名称" lazy="false"(延迟加载选项) cascade="all|none" (是否级联) order-by="某属性 asc">
<key column="外键列名"></key>
<one-to many class ="另一个类的名称"/>
</set>
Banji.java:
package PO;
import java.util.Set;
public class Banji {
private int banjihao;
private String banjiming;
private Set students;
public int getBanjihao() {
return banjihao;
}
public void setBanjihao(int banjihao) {
this.banjihao = banjihao;
}
public String getBanjiming() {
return banjiming;
}
public void setBanjiming(String banjiming) {
this.banjiming = banjiming;
}
public Set getStudents() {
return students;
}
public void setStudents(Set students) {
this.students = students;
}
}
因为一个班级里面有许多学生,所以students的类型是set,但是系统还是不认识这个set类型的students,所以需要在映射文件里面进行注册。
Banji.hbm.xml:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="PO.Banji" table="Banji">
<id name="banjihao" column="班级号" >
<generator class="assigned"></generator>
</id>
<property name="banjiming" column="班级名字" ></property>
<set name="students" table="student" lazy="false" cascade="all" order-by="xuehao asc">
<key column="班级号"></key>
<one-to-many class="PO.Student"/>
</set>
</class>
</hibernate-mapping>
Query1.java:查询一班内所有学生
package Test;
import PO.Banji;
import PO.Student;
import org.hibernate.Session;
import java.util.Iterator;
import java.util.Set;
public class Query1 {
public static void main(String[] args) {
Session session=util.HibernateSessionFactory.getSession();
//查询一班的所有学生
Banji banji =(Banji)session.get(Banji.class,1);
System.out.println(banji.getBanjiming());
Set set=banji.getStudents();
Iterator iterator=set.iterator();
while(iterator.hasNext()){
Student student=(Student)iterator.next();
System.out.println(student.getXingming());
}
util.HibernateSessionFactory.closeSession();
}
}
结果如下:
一年一班的小明和小王都显示在控制台上了。
查找流程
当开始查找学生信息的,系统会去Banji的映射文件里面去找,因为配置的students是set类型,所以系统知道students的类型是存在放student这个类里面的。
然后根据table,系统会去student这个表里面去找学生的信息,寻找的时候,以当前Banji这个表的主键——banjihao和另外一个表的主键——banjihao去数据库里面查找。然后把结果存放用Student类包装起来,放在students里面。
lazy懒加载
上面用到的懒加载一般是用false,这样的查询都是即时的,哪怕session关闭后也不用担心数据消失。
如果采用了懒加载,而session又在资源使用之前关闭了,系统是会抛出一个异常的。
删除
Delete1.java:
package Test;
import PO.Banji;
import org.hibernate.Session;
import org.hibernate.Transaction;
public class Delete1 {
public static void main(String[] args) {
Session session =util.HibernateSessionFactory.getSession();
Banji banji=(Banji)session.get(Banji.class,1);
Transaction transaction=session.beginTransaction();
session.delete(banji);
transaction.commit();
util.HibernateSessionFactory.closeSession();
}
}
此时会把一班和一班的所有学生都删除。数据库就变成了这个样子。
一班和一班的学生都被删除了。
插入
package Test;
import PO.Banji;
import PO.Student;
import org.hibernate.Session;
import org.hibernate.Transaction;
import java.util.HashSet;
public class Update {
public static void main(String[] args) {
Session session=util.HibernateSessionFactory.getSession();
Transaction transaction=session.beginTransaction();
Student student1=new Student();
student1.setXuehao(10);
student1.setXingming("小李子123");
student1.setBanjihao(4);
Student student2=new Student();
student2.setXuehao(11);
student2.setXingming("小李子子");
student2.setBanjihao(4);
HashSet hashSet=new HashSet();
hashSet.add(student1);
hashSet.add(student2);
Banji banji=new Banji();
banji.setBanjihao(4);
banji.setBanjiming("一年四班");
banji.setStudents(hashSet);
session.save(banji);
transaction.commit();
util.HibernateSessionFactory.closeSession();
}
}