目录
学习笔记,为了加强记忆和深入理解在此记录备忘。如有错误和理解不当之处,还望指正。万分感谢!
另外,实例和内容有些是参照网络其他博文,如有侵权可联系删除。
学习重点:
1、一对一主键关联和外键关联
一对一有单向和双向、主键关联外键关联之分,在前面(一对多)已经介绍过单向和双向的区别,所以这里不再描述单向和双向。
以教师和学生为例:
假设一个老师教一个学生知识;
假设一个学生向一个老师学习;
一、一对一主键关联(双向)
什么是主键关联:以老师为主,学生编号既是自己的主键同时是教师编号的外键;这样导致老师可以不教学生,但是学生必须向一个老师学习,这也是主外键的约束。
1.1 教师实体类Teacher.java
package demo.entity;
public class Teacher {
private int teaId;
private String teaName;
// 引入学生对象
private Student student;
public int getTeaId() {
return teaId;
}
public void setTeaId(int teaId) {
this.teaId = teaId;
}
public String getTeaName() {
return teaName;
}
public void setTeaName(String teaName) {
this.teaName = teaName;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
}
1.2 学生实体类Student.java
package demo.entity;
public class Student {
private int stuId;
private String stuName;
// 引入教师对象
private Teacher teacher ;
public int getStuId() {
return stuId;
}
public void setStuId(int stuId) {
this.stuId = stuId;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
}
1.3 教师映射文件Teacher.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">
<!-- Generated 2018-7-27 11:16:28 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<class name="demo.entity.Teacher" table="t_teacher">
<id name="teaId" type="int">
<column name="teaId" />
<generator class="native" />
</id>
<property name="teaName" type="java.lang.String">
<column name="teaName" />
</property>
<!-- name:是实体类中引入的属性名 -->
<one-to-one name="student" class="demo.entity.Student" />
</class>
</hibernate-mapping>
1.4 学生映射文件Student.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">
<!-- Generated 2018-7-27 11:16:28 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<class name="demo.entity.Student" table="t_student">
<id name="stuId" type="int" column="stuId">
<!-- 重点在这里。 因为主键跟外键是同一个,所以直接在这里申明该主键就是外键 -->
<generator class="foreign">
<!-- 外键指向申明的对象teacher -->
<param name="property">teacher</param>
</generator>
</id>
<property name="stuName" type="java.lang.String">
<column name="stuName" />
</property>
<!-- 一对一配置,name是实体类申明的属性-->
<one-to-one name="teacher" class="demo.entity.Teacher" />
</class>
</hibernate-mapping>
1.5 测试类
package demo.test;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import demo.entity.Student;
import demo.entity.Teacher;
class JunitTest {
private Configuration configuration = new Configuration().configure();
private SessionFactory sFactory = configuration.buildSessionFactory();
private Session session = null;
private Transaction transaction = null;
@BeforeEach
void setUp() throws Exception {
session = sFactory.openSession();
transaction = session.beginTransaction();
}
@AfterEach
void tearDown() throws Exception {
transaction.commit();
session.close();
}
@Test
void testSave() {
Teacher teacher = new Teacher();
teacher.setTeaName("老师1");
Student student = new Student();
student.setStuName("学生1");
student.setTeacher(teacher);
session.save(teacher);
session.save(student);
}
}
二、一对一外键关联(双向)
外键关联是多对一的特例,相对于主键关联学生在数据库表中多出一个老师编号的字段,它是老师编号的外键。
2.1 实体类
和主键关联的实体类一样,主要区别是在映射文件
2.2 教师映射文件Teacher.hbm.xml
和主键关联的区别是:新增property-ref属性。
如果没有指定会使用对方关联类的主键来跟本类的主键比较,这里要注意不是关联表中的外键字段名,是对象属性。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2018-7-27 11:16:28 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<class name="demo.entity.Teacher" table="t_teacher">
<id name="teaId" type="int">
<column name="teaId" />
<generator class="native" />
</id>
<property name="teaName" type="java.lang.String">
<column name="teaName" />
</property>
<!--
name:是实体类中引入的属性名
property-ref:指定关联类的属性名(学生中申明的老师对象),
这个属性将会和本类的主键相对应
-->
<one-to-one name="student" class="demo.entity.Student" property-ref="teacher" />
</class>
</hibernate-mapping>
2.3 学生映射文件Student.hbm.xml
这里和主键关联的区别是:主键策略正常配置,one-to-one改为many-to-one。
另外这里需要注意保存顺序,先保存主的一方(教师),可以减少update。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2018-7-27 11:16:28 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<class name="demo.entity.Student" table="t_student">
<id name="stuId" type="int" column="stuId">
<!-- 正常配置 -->
<generator class="native" />
</id>
<property name="stuName" type="java.lang.String">
<column name="stuName" />
</property>
<!--
一对一配置,name是实体类申明的属性
column是数据库外键字段名
由于是多对一的特例,所以需要加unique属性
-->
<many-to-one name="teacher" class="demo.entity.Teacher"
column="teaId" unique="true" />
</class>
</hibernate-mapping>
三、总结
3.1 映射文件的主要差别
属性 | 主键关联 | 外键关联 | ||
主 | 从 | 主 | 从 | |
主键策略 | 正常配置 | <id name="stuId" 使用foriegn,并且param指定主键 | 正常配置 | 正常配置 |
对应关系 | <one-to-one name="student" class="demo.entity.Student" /> 一对一正常配置 | <one-to-one name="student" 一对一正常配置 | <one-to-one name="student" 指定property-ref属性(必须) | <many-to-one name="teacher" 使用many-to-one指定unique |