Hibernate 一对多映射(单向查询/双向查询)
>> 查询一个学校(School)中的所有学生(Student)姓名信息。
实现过程
1. Stduent.java
加入School对象,用于表明本学生的学校信息。
package com.java1234.hibernate.model;
public class Student {
private int id;
private String name;
private School school;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "]";
}
}
2. School.java
加入Set<Student>用于映射本校学生信息。
package com.java1234.hibernate.model;
import java.util.Set;
public class School {
private int id;
private String name;
private Set<Student> students;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
}
3. student.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.java1234.hibernate.model.Student" table="tb_student">
<id name="id" column="stuId">
<generator class="native"/>
</id>
<property name="name" column="stuName"/>
<!-- 声明tb_Stduent表中的外键,通过本属性完成Student-School的连接 -->
<many-to-one name="school" cascade="save-update" column="schoolId" class="com.java1234.hibernate.model.School" />
</class>
</hibernate-mapping>
4. school.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.java1234.hibernate.model.School" table="tb_school">
<id name="id" column="schoolId">
<generator class="native"/>
</id>
<property name="name" column="schoolName"/>
<set name="students" cascade="save-update">
<!-- 对应student.hbm.xml中的外键 ,通过本属性完成School-Student的连接-->
<key column="schoolId"/>
<one-to-many class="com.java1234.hibernate.model.Student"/>
</set>
</class>
</hibernate-mapping>
5. 生成表结构
SQL: 生成两个表,然后在student表中指定外键,以连接school表。
Hibernate: create table tb_school (schoolId integer not null auto_increment, schoolName varchar(255), primary key (schoolId))
Hibernate: create table tb_student (stuId integer not null auto_increment, stuName varchar(255), schoolId integer, primary key (stuId))
Hibernate: alter table tb_student add constraint FK_9r9feouw7ag48dhdi4eyoykxv foreign key (schoolId) references tb_school (schoolId)
图示:
6. 插入数据。
@Test
public void testInsert(){
session.beginTransaction();
School school1 = new School();
school1.setName("No.23 Middle School");
School school2 = new School();
school2.setName("No.98 Middle School");
Student student1 = new Student();
student1.setName("Robin");
student1.setSchool(school1);
Student student2 = new Student();
student2.setName("Mary");
student2.setSchool(school1);
Student student3 = new Student();
student3.setName("Gery");
student3.setSchool(school2);
session.save(student1);
session.save(student2);
session.save(school2);
session.getTransaction().commit();
}
在此过程中产生的SQL:
由于在student.hbm.xml中添加了cacsde='save-update'属性,所以在保存student对象时,会把相应的school信息一同保存进数据库; 而在school.hbm..xml中未添加cascade属性,由于其默认值为null, 所以在执行保存school对象时不对添加对应的student。
Hibernate: insert into tb_school (schoolName) values (?)
Hibernate: insert into tb_student (stuName, schoolId) values (?, ?)
Hibernate: insert into tb_student (stuName, schoolId) values (?, ?)
Hibernate: insert into tb_school (schoolName) values (?)
7. 删除数据
如果使用 cascade='delete' 级联删除,在删除student数据时 会自动删除对应的school数据。