Hibernate框架支持通过配置映射关系实现多表关联查询。
关联查询分为:一对一(one-to-one)、一对多(one-to-many)、多对一(many-to-one)、多对多(many-to-many)。
当一个POJO对象中包含了一个对象属性或者集合属性时,使用一般的Hibernate的查询无法完成对象或者集合的映射,此时就需要使用Hibernate的关联查询。
总结:关联查询需要在原先配置的基础上增加对象属性和集合属性的配置关系。
SET SESSION FOREIGN_KEY_CHECKS=0;
/* Drop Tables */
DROP TABLE IF EXISTS tb_result;
DROP TABLE IF EXISTS tb_student_identifer;
DROP TABLE IF EXISTS tb_student_teacher;
DROP TABLE IF EXISTS tb_student;
DROP TABLE IF EXISTS tb_teacher;
/* Create Tables */
-- 成绩表
CREATE TABLE tb_result
(
result_id int NOT NULL AUTO_INCREMENT COMMENT '成绩编号',
result_subject varchar(50) COMMENT '科目',
result_score float COMMENT '分数',
student_id int NOT NULL COMMENT '学生编号',
PRIMARY KEY (result_id)
) COMMENT = '成绩表';
-- 学生表
CREATE TABLE tb_student
(
student_id int NOT NULL AUTO_INCREMENT COMMENT '学生编号',
student_name varchar(50) COMMENT '学生名',
student_pwd varchar(50) COMMENT '密码',
PRIMARY KEY (student_id)
) COMMENT = '学生表';
-- 学生身份信息表
CREATE TABLE tb_student_identifer
(
student_id int NOT NULL COMMENT '学生编号',
student_idcard varchar(30) COMMENT '身份证号码',
student_number varchar(50) COMMENT '学号',
PRIMARY KEY (student_id)
) COMMENT = '学生身份信息表';
-- 学生教师关系表
CREATE TABLE tb_student_teacher
(
student_id int NOT NULL COMMENT '学生编号',
teacher_id int NOT NULL COMMENT '教师编号'
) COMMENT = '学生教师关系表';
-- 教师表
CREATE TABLE tb_teacher
(
teacher_id int NOT NULL AUTO_INCREMENT COMMENT '教师编号',
teacher_name varchar(50) COMMENT '教师名字',
teacher_pwd varchar(50) COMMENT '登录密码',
PRIMARY KEY (teacher_id)
) COMMENT = '教师表';
根据数据库表,建立对应的POJO以及映射文件。
注意:多对多的关联表只做关联桥梁,不生成POJO对象。
--pojo:
public class Student {
private Integer studentId; // 学生编号
private String StudentName; // 姓名
private String studentPwd; // 密码
// get、set方法
}
——————————————————————————
public class StudentIdentifer {
private Integer studentId;
private String studentIdcard;
private String studentNumber;
// get、set方法
}
——————————————————————————
public class Teacher {
private Integer teacherId;
private String teacherName;
private String teacherPwd;
// get、set方法
}
——————————————————————————
public class Result {
private Integer resultId;
private String resultSubject;
private Float resultScore;
private Integer studentId;
// get、set方法
}
xxx.hbm.xml:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.brick.pojo.Student" table="tb_student">
<!-- 配置主键 -->
<id name="studentId" column="student_id">
<generator class="identity"></generator>
</id>
<!-- 配置一般属性 -->
<property name="studentName" column="student_name" />
<property name="studentPwd" column="student_pwd" />
<!-- 配置StudentIdentifier属性 -->
<one-to-one name="studentIdentifer" foreign-key="student_id"/>
</class>
</hibernate-mapping>
——————————————————————————————————————————
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.brick.pojo.StudentIdentifer" table="tb_student_identifer">
<!-- 配置主键 -->
<id name="studentId" column="student_id">
<generator class="identity"></generator>
</id>
<!-- 配置一般属性 -->
<property name="studentIdcard" column="student_idcard" />
<property name="studentNumber" column="student_number" />
</class>
</hibernate-mapping>
——————————————————————————————————————————
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.brick.pojo.Teacher" table="tb_teacher">
<!-- 配置主键 -->
<id name="teacherId" column="teacher_id">
<generator class="identity"></generator>
</id>
<!-- 配置一般属性 -->
<property name="teacherName" column="teacher_name" />
<property name="teacherPwd" column="teacher_pwd" />
</class>
</hibernate-mapping>
——————————————————————————————————————————
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.brick.pojo.Result" table="tb_result">
<!-- 配置主键 -->
<id name="resultId" column="result_id">
<generator class="identity"></generator>
</id>
<!-- 配置一般属性 -->
<property name="resultSubject" column="result_subject" />
<property name="resultScore" column="result_score" />
<property name="studentId" column="student_id" />
</class>
</hibernate-mapping>
(1)需求
通过学生信息,查询学生的身份信息。
这里使用ErMaster来构建ER图。
学生表和学生身份信息表的ER图:
(2)配置步骤说明
配置表与表的关系,步骤就两步:
第一步:根据数据库设计,将表与表之间的关系建立在实体类里面。
第二步:在对应的映射文件,配置映射的关系。
注意:通过入门示例修改代码,框架配置代码在本文忽略了,参考Hibernate【入门篇】 XXXXX。
(3)配置步骤
第一步:配置实体类的关联关系
修改学生对象,将学生身份对象作为学生对象的一个对象属性存在。
public class Student {
private Integer studentId; // 学生编号
private String StudentName; // 姓名
private String studentPwd; // 密码
// 需求:通过studentId查询学生身份信息
private StudentIdentifer studentIdentifer;
public StudentIdentifer getStudentIdentifer() {
return studentIdentifer;
}
public void setStudentIdentifer(StudentIdentifer studentIdentifer) {
this.studentIdentifer = studentIdentifer;
}
// get、set方法
}
第二步:配置映射关系
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.brick.pojo.Student" table="tb_student">
<!-- 配置主键 -->
<id name="studentId" column="student_id">
<generator class="identity"></generator>
</id>
<!-- 配置一般属性 -->
<property name="studentName" column="student_name" />
<property name="studentPwd" column="student_pwd" />
<!-- 配置StudentIdentifier属性 -->
<one-to-one name="studentIdentifer" foreign-key="student_id"/>
</class>
</hibernate-mapping>
第三步:测试
@Test
public void findById() {
Session session = null;
try {
session = HibernateUtil.getSession();
System.out.println(session);
// 通过Id查询使用get方法
Student student = session.get(Student.class, 1);
System.out.println("编号:" + student.getStudentId() + ", 学生名:" + student.getStudentName());
StudentIdentifer identifer = student.getStudentIdentifer();
System.out.println("学生身份证:" + identifer.getStudentIdcard());
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
}
(1)需求
通过学生表的记录,查询学生的成绩记录。
学生表和成绩表的ER图:
(2)配置步骤
第一步:配置实体类的关联关系
一个学生对应多个考试成绩,所以考试成绩作为学生对象的一个集合属性存在。
在学生实体类Student加上以下代码。
private Set<Result> results;
public Set<Result> getResults() {
return results;
}
public void setResults(Set<Result> results) {
this.results = results;
}
第二步:配置映射关系
在student.hbm.xml配置文件中加入如下配置。
<!-- 配置学生和成绩的"一对多关系" -->
<!-- set标签用于配置Set集合,list标签对应List集合 -->
<set name="results">
<!-- 用于指定外键字段 -->
<key column="student_id" />
<!-- 用于指定一对多关系,class属性:指定集合元素类型 -->
<one-to-many class="org.brick.pojo.Result" />
</set>
第三步:测试
@Test
public void findById() {
Session session = null;
try {
session = HibernateUtil.getSession();
System.out.println(session);
// 通过Id查询使用get方法
Student student = session.get(Student.class, 1);
System.out.println("编号:" + student.getStudentId() + ", 学生名:" + student.getStudentName());
Set<Result> results = student.getResults();
for (Result result : results) {
System.out.println("科目:" + result.getResultSubject() + ", 成绩:" + result.getResultScore());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
}
(1)需求
通过成绩信息查询学生信息。
(2)配置步骤
第一步:配置实体类的关联关系
在成绩对象(Result)中配置学生对象属性,以表示成绩表和学生表的对应关系为多对一。
在Result对象中加入以下代码。
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
第二步:配置映射关系
修改配置文件,第一步:注释掉原外键配置,第二步:配置多对一关系。
<!--
[1] 注释掉外键字段配置
-->
<!--<property name="studentId" column="student_id" />-->
<!--
[2] 配置成绩和学生的"多对一"关系
name属性:配置多对一的属性名
column属性:配置关联的外键字段
-->
<many-to-one name="student" column="student_id" />
第三步:测试
@Test
public void findById() {
Session session = null;
try {
session = HibernateUtil.getSession();
System.out.println(session);
// 通过Id查询使用get方法
Result result = session.get(Result.class, 1);
Student student = result.getStudent();
System.out.println("学生Id:" + student.getStudentId() + ", 科目:" + result.getResultSubject() + ", 成绩:" + result.getResultScore());
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
}
(1)需求
通过学生的记录查询学生的教师记录。
学生表、老师表、学生老师表的ER图:
(2)配置步骤
第一步:配置实体类的关联关系
配置学生表与教师表的关系,这里在Student类中添加Teacher集合,因此在Student实体类加上以下代码。
private Set<Teacher> teachers;
public Set<Teacher> getTeachers() {
return teachers;
}
public void setTeachers(Set<Teacher> teachers) {
this.teachers = teachers;
}
第二步:配置映射关系
<!-- 配置学生与教师的多对多关系 -->
<!--
name属性:关联字段名
table:多对多中间表名
-->
<set name="teachers" table="tb_student_teacher">
<!-- 指定本表在中间表的外键 -->
<key column="student_id"/>
<!-- 指定多对多关系 -->
<!--
class:返回集合的元素类型
column:关联表在中间表的外键
-->
<many-to-many class="org.brick.pojo.Teacher" column="teacher_id" />
</set>
第三步:测试
@Test
public void findById() {
Session session = null;
try {
session = HibernateUtil.getSession();
System.out.println(session);
// 通过Id查询使用get方法
Student student = session.get(Student.class, 1);
Set<Teacher> teachers = student.getTeachers();
for (Teacher teacher : teachers) {
System.out.println("学生名:" + student.getStudentName() + ", 老师名:" + teacher.getTeacherName());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
}
你适合学Java吗?4大专业测评方法
代码逻辑 吸收能力 技术学习能力 综合素质
先测评确定适合在学习