一、Hinbernate中持久化类的关联关系

在数据库中,表表之间是通过外键关联的,在程序中是要转化为持久化类也就是(JAVA Bean)来实例的。

但在Hibernater中持久化的之间的映射关系,不是通外键建立关联,而是通过属性.主要有以下几种

  • 一对一,
  • 一对多(多对一)
  • 多对多

关联方向:

  • 单向关联
  • 双向关联

二、一对多单向关联关系

2.1、建立数据库表

班级表,和学生表,学生生通过班级表中的,班级编号为外键

--班级表
create table grade
(
gid number primary key, --班级ID
gname varchar2(50), --班级名称
gdesc varchar2(50) --班级介绍
);
--学生表
create table student
(
sid number primary key, --主键ID学生ID
sname varchar2(20), --学生姓名
sex varchar2(20), --学生性别
gid number references grade(gid) ---外键班级ID
);

2.2、建立持久化类和映射配置文件

班级和学生类

package entity;

import java.util.HashSet;
import java.util.Set; /*
* 班级类
*/
public class Grade implements java.io.Serializable { // Fields
private static final long serialVersionUID = 1L;
private int gid;
private String gname;
private String gdesc;
private Set<Student> students = new HashSet<Student> (); // Constructors /** default constructor */
public Grade() {
} /** minimal constructor */
public Grade(int gid) {
this.gid = gid;
} /** full constructor */
public Grade(int gid, String gname, String gdesc, Set<Student> students) {
this.gid = gid;
this.gname = gname;
this.gdesc = gdesc;
this.students = students;
} // Property accessors public int getGid() {
return this.gid;
} public void setGid(int gid) {
this.gid = gid;
} public String getGname() {
return this.gname;
} public void setGname(String gname) {
this.gname = gname;
} public String getGdesc() {
return this.gdesc;
} public void setGdesc(String gdesc) {
this.gdesc = gdesc;
} public Set<Student> getStudents() {
return this.students;
} public void setStudents(Set<Student> students) {
this.students = students;
} }

学生类

package entity;

/*
* 学生类
*/
public class Student implements java.io.Serializable { // Fields private static final long serialVersionUID = 1L;
private int sid; private String sname;
private String sex; // Constructors /** default constructor */
public Student() {
} /** minimal constructor */
public Student(int sid) {
this.sid = sid;
} /** full constructor */
public Student(int sid, String sname, String sex ) { this.sid = sid; this.sname = sname;
this.sex = sex;
} // Property accessors public int getSid() {
return this.sid;
} public void setSid(int sid) {
this.sid = sid;
} public String getSname() {
return this.sname;
} public void setSname(String sname) {
this.sname = sname;
} public String getSex() {
return this.sex;
} public void setSex(String sex) {
this.sex = sex;
} }

hibernate.cf.xml和班级、学生的配置文件

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory>
<property name="dialect">
org.hibernate.dialect.Oracle9Dialect
</property>
<property name="connection.url">
jdbc:oracle:thin:@localhost:1521:orcl
</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.driver_class">
oracle.jdbc.OracleDriver
</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property> <mapping resource="entity/Grade.hbm.xml" />
<mapping resource="entity/Student.hbm.xml" /> </session-factory> </hibernate-configuration>

持久类配置先来学生类

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping>
<class name="entity.Student" table="STUDENT" schema="ROOT">
<id name="sid" type="java.lang.Integer">
<column name="SID" precision="22" scale="0" />
<generator class="assigned" />
</id>
<property name="sname" type="java.lang.String">
<column name="SNAME" length="20" />
</property>
<property name="sex" type="java.lang.String">
<column name="SEX" length="20" />
</property>
</class>
</hibernate-mapping>

班级类配置

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping>
<class name="entity.Grade" table="GRADE" schema="ROOT">
<id name="gid" type="java.lang.Integer">
<column name="GID" precision="22" scale="0" />
<generator class="assigned" />
</id>
<property name="gname" type="java.lang.String">
<column name="GNAME" length="50" />
</property>
<property name="gdesc" type="java.lang.String">
<column name="GDESC" length="50" />
</property>
<!--建立set属性,也可以建立list和持久化类中一致就行 -->
<set name="students">
<key>
<!--这里的列是指学生表中的班级编号 -->
<column name="GID" precision="22" scale="0" />
</key>
<!-- 通过class属性指定set的属性 -->
<one-to-many class="entity.Student" />
</set>
</class>
</hibernate-mapping>

测试类

package Test;

import java.util.Set;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration; import entity.Grade;
import entity.Student; public class Demo1 { /**
* 测试类
*/
public static void main(String[] args) {
save();
find();
update(); } public static void save() {
// 声明班级对象,并赋值
Grade grade = new Grade();
grade.setGid(201504);
grade.setGname("Java一班");
grade.setGdesc("刚开始学习JAVA");
// 声明2个学生对象
Student stu1 = new Student();
stu1.setSid(201504012);
stu1.setSname("张三");
stu1.setSex("男"); Student stu2 = new Student();
stu2.setSid(201504013);
stu2.setSname("李四");
stu2.setSex("女"); // 将学生添加到班级
grade.getStudents().add(stu1);
grade.getStudents().add(stu2);
// 建立session
Session session = new Configuration().configure().buildSessionFactory()
.openSession();
// 开始事务
Transaction transaction = session.beginTransaction();
// 保存班级
session.save(grade);
// 保存学生
session.save(stu1);
session.save(stu2);
// 提交事务
transaction.commit();
// 关闭session
session.close();
} /*
* 将基中一个学生更改为别一个班级
*/
public static void update() {
// 声明班级对象,并赋值
Grade grade = new Grade();
grade.setGid(201506);
grade.setGname("Java二班");
grade.setGdesc("学习JAVA二年级");
// 获取一个学生的信息
// 建立session
Session session = new Configuration().configure().buildSessionFactory()
.openSession();
// 开始事务
Transaction transaction = session.beginTransaction();
Student stu1=(Student) session.get(Student.class, 201504013);
//将学生添加到这个新的班级
grade.getStudents().add(stu1);
// 保存班级
session.save(grade);
// 保存学生
session.save(stu1);
// 提交事务
transaction.commit();
// 关闭session
session.close();
} // 查询班级
public static void find() { // 建立session
Session session = new Configuration().configure().buildSessionFactory()
.openSession();
Grade g = (Grade) session.get(Grade.class, 201504);
System.out.println("班级信息:" + g.getGid() + "\t" + g.getGname()
+ g.getGdesc());
// 通过班级获取这个班级的学生信息
System.out.println("201504班的学生信息如下:");
Set<Student> set = g.getStudents();
for (Student stu : set) {
System.out.println(stu.getSid() + "\t" + stu.getSname() + "\t"
+ stu.getSex());
}
} }

以上只上单向关联,一般都会有双向关联

同样要在学生类中添加Grade 属性

在学生类的配置文件中配置关联字段

二、建立双向关联

2.1、更改学生类和配置文件

package entity;

/*
* 学生类
*/
public class Student implements java.io.Serializable { // Fields private static final long serialVersionUID = 1L;
private int sid;
private String sname;
private String sex;
//增加班级属性
private Grade grade; // Constructors /** default constructor */
public Student() {
} /** minimal constructor */
public Student(int sid) {
this.sid = sid;
} /** full constructor */
public Student(int sid, String sname, String sex ) { this.sid = sid; this.sname = sname;
this.sex = sex;
} // Property accessors public int getSid() {
return this.sid;
} public void setSid(int sid) {
this.sid = sid;
} public String getSname() {
return this.sname;
} public void setSname(String sname) {
this.sname = sname;
} public String getSex() {
return this.sex;
} public void setSex(String sex) {
this.sex = sex;
} public Grade getGrade() {
return grade;
} public void setGrade(Grade grade) {
this.grade = grade;
} }

配置文件

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping>
<class name="entity.Student" table="STUDENT" schema="ROOT">
<id name="sid" type="java.lang.Integer">
<column name="SID" precision="22" scale="0" />
<generator class="assigned" />
</id>
<property name="sname" type="java.lang.String">
<column name="SNAME" length="20" />
</property>
<property name="sex" type="java.lang.String">
<column name="SEX" length="20" />
</property>
<!--配置grade属性 -->
<many-to-one name="grade" class="entity.Grade">
<!--指定学生表中的外键 -->
<column name="GID" />
</many-to-one>
</class>
</hibernate-mapping>

2.2、测试类

建立双向关联后,就可以通过学生来获取班级信息

清空数据表中的数据

package Test;

import org.hibernate.Session;
import org.hibernate.cfg.Configuration; import entity.Student; public class Demo2 { /**
* 测试类
*/
public static void main(String[] args) {
 save();
findByStu();
} public static void findByStu(){
Session session = new Configuration().configure().buildSessionFactory()
.openSession();
//获取一个学生的信息 get方法为通过主键查询
Student stu=(Student) session.get(Student.class, 201504013);
System.out.println("学生信息:\t"+stu.getSid()+"\t"+stu.getSname()+"\t"+stu.getSex());
//通过学生信息得到班级信息
System.out.println("这个学生的班级信息:"+stu.getGrade().getGid()+"\t"+stu.getGrade().getGname()+"\t"+stu.getGrade().getGdesc());
}
}
public static void save() {
// 声明班级对象,并赋值
Grade grade = new Grade();
grade.setGid(201504);
grade.setGname("Java一班");
grade.setGdesc("刚开始学习JAVA");
// 声明2个学生对象
Student stu1 = new Student();
stu1.setSid(201504012);
stu1.setSname("张三");
stu1.setSex("男");
stu1.setGrade(grade); Student stu2 = new Student();
stu2.setSid(201504013);
stu2.setSname("李四");
stu2.setSex("女");
stu2.setGrade(grade);
// 将学生添加到班级
/*grade.getStudents().add(stu1);
grade.getStudents().add(stu2);*/
// 建立session
Session session = new Configuration().configure().buildSessionFactory()
.openSession();
// 开始事务
Transaction transaction = session.beginTransaction();
// 保存班级
session.save(grade);
// 保存学生
session.save(stu1);
session.save(stu2);
// 提交事务
transaction.commit();
// 关闭session
session.close();
}

三、级联保存和删除

能不能只保存学生时,同时保存班级呢,或者保存班级时,同时保存学生呢

3.1、cascade属性

保存班级时,同时保存学生信息

修改班级配置,在set标签中添加cascade属性,设置为save-update

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping>
<class name="entity.Grade" table="GRADE" schema="ROOT">
<id name="gid" type="java.lang.Integer">
<column name="GID" precision="22" scale="0" />
<generator class="assigned" />
</id>
<property name="gname" type="java.lang.String">
<column name="GNAME" length="50" />
</property>
<property name="gdesc" type="java.lang.String">
<column name="GDESC" length="50" />
</property>
<!--建立set属性,也可以建立list和持久化类中一致就行 -->
<set name="students" cascade="save-update">
<key>
<!--这里的列是指学生表中的班级编号 -->
<column name="GID" precision="22" scale="0" />
</key>
<!-- 通过class属性指定set的属性 -->
<one-to-many class="entity.Student" />
</set>
</class>
</hibernate-mapping>

测试类

package Test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration; import entity.Grade;
import entity.Student; public class Demo3 { /**
* @param args
*/
public static void main(String[] args) {
save(); }
public static void save() {
// 声明班级对象,并赋值
Grade grade = new Grade();
grade.setGid(201504);
grade.setGname("Java一班");
grade.setGdesc("刚开始学习JAVA");
// 声明2个学生对象
Student stu1 = new Student();
stu1.setSid(201504012);
stu1.setSname("张三");
stu1.setSex("男");
stu1.setGrade(grade); Student stu2 = new Student();
stu2.setSid(201504013);
stu2.setSname("李四");
stu2.setSex("女");
stu2.setGrade(grade);
// 将学生添加到班级
grade.getStudents().add(stu1);
grade.getStudents().add(stu2);
// 建立session
Session session = new Configuration().configure().buildSessionFactory()
.openSession();
// 开始事务
Transaction transaction = session.beginTransaction();
// 保存班级
session.save(grade);
// 保存学生
//session.save(stu1);
//session.save(stu2);
// 提交事务
transaction.commit();
// 关闭session
session.close();
}
}

反之,在学生类的配置文件one-many中添加cascade属性设置为save-update

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping>
<class name="entity.Student" table="STUDENT" schema="ROOT">
<id name="sid" type="java.lang.Integer">
<column name="SID" precision="22" scale="0" />
<generator class="assigned" />
</id>
<property name="sname" type="java.lang.String">
<column name="SNAME" length="20" />
</property>
<property name="sex" type="java.lang.String">
<column name="SEX" length="20" />
</property>
<!--配置grade属性 -->
<many-to-one name="grade" class="entity.Grade" cascade="save-update">
<!--指定学生表中的外键 -->
<column name="GID" />
</many-to-one>
</class>
</hibernate-mapping>
package Test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration; import entity.Grade;
import entity.Student; public class Demo3 { /**
* @param args
*/
public static void main(String[] args) {
save(); }
public static void save() {
// 声明班级对象,并赋值
Grade grade = new Grade();
grade.setGid(201504);
grade.setGname("Java一班");
grade.setGdesc("刚开始学习JAVA");
// 声明2个学生对象
Student stu1 = new Student();
stu1.setSid(201504012);
stu1.setSname("张三");
stu1.setSex("男");
stu1.setGrade(grade); Student stu2 = new Student();
stu2.setSid(201504013);
stu2.setSname("李四");
stu2.setSex("女");
stu2.setGrade(grade);
// 将学生添加到班级
grade.getStudents().add(stu1);
grade.getStudents().add(stu2);
// 建立session
Session session = new Configuration().configure().buildSessionFactory()
.openSession();
// 开始事务
Transaction transaction = session.beginTransaction();
// 保存班级
//session.save(grade);
// 保存学生
session.save(stu1);
session.save(stu2);
// 提交事务
transaction.commit();
// 关闭session
session.close();
}
}

3.2、inverse属性

首先在班级类中设置invers属性为false时,删除班级

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping>
<class name="entity.Grade" table="GRADE" schema="ROOT">
<id name="gid" type="java.lang.Integer">
<column name="GID" precision="22" scale="0" />
<generator class="assigned" />
</id>
<property name="gname" type="java.lang.String">
<column name="GNAME" length="50" />
</property>
<property name="gdesc" type="java.lang.String">
<column name="GDESC" length="50" />
</property>
<!--建立set属性,也可以建立list和持久化类中一致就行 -->
<set name="students" cascade="save-update" inverse="false">
<key>
<!--这里的列是指学生表中的班级编号 -->
<column name="GID" precision="22" scale="0" />
</key>
<!-- 通过class属性指定set的属性 -->
<one-to-many class="entity.Student" />
</set>
</class>
</hibernate-mapping>

测试类

package Test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration; import entity.Grade;
import entity.Student; public class Demo4 { /**
* @param args
*/
public static void main(String[] args) {
delete() ; } public static void delete() { // 建立session
Session session = new Configuration().configure().buildSessionFactory()
.openSession();
// 开始事务
Transaction transaction = session.beginTransaction();
// 保存班级
Grade grade=(Grade) session.get(Grade.class, 201504);
// 保存学生
session.delete(grade);
// 提交事务
transaction.commit();
// 关闭session
session.close();
}
}

结果:发现班级表中的班级已经删除,而学生表中数据没有删除,只是GID字段为NULL

下面将inverse设置为true时,添加新学生,和新的班级

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping>
<class name="entity.Grade" table="GRADE" schema="ROOT">
<id name="gid" type="java.lang.Integer">
<column name="GID" precision="22" scale="0" />
<generator class="assigned" />
</id>
<property name="gname" type="java.lang.String">
<column name="GNAME" length="50" />
</property>
<property name="gdesc" type="java.lang.String">
<column name="GDESC" length="50" />
</property>
<!--建立set属性,也可以建立list和持久化类中一致就行 -->
<set name="students" cascade="save-update" inverse="true">
<key>
<!--这里的列是指学生表中的班级编号 -->
<column name="GID" precision="22" scale="0" />
</key>
<!-- 通过class属性指定set的属性 -->
<one-to-many class="entity.Student" />
</set>
</class>
</hibernate-mapping>

测试类

package Test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration; import entity.Grade;
import entity.Student; public class Demo4 { /**
* @param args
*/
public static void main(String[] args) {
delete() ; } public static void delete() { // 声明班级对象,并赋值
Grade grade = new Grade();
grade.setGid(201509);
grade.setGname("Java三班");
grade.setGdesc("ASP.NET");
// 声明2个学生对象
Student stu1 = new Student();
stu1.setSid(201509009);
stu1.setSname("王五");
stu1.setSex("女");
stu1.setGrade(grade); Student stu2 = new Student();
stu2.setSid(201509045);
stu2.setSname("赵六");
stu2.setSex("女");
stu2.setGrade(grade); // 建立session
Session session = new Configuration().configure().buildSessionFactory()
.openSession();
// 开始事务
Transaction transaction = session.beginTransaction(); // 保存学生
session.save(stu1);
session.save(stu2);
// 提交事务
transaction.commit();
// 关闭session
session.close();
}
}

结果发现,我并没有用班级添加学生,也没有保存班级,只是保存了学生,班级信息一起保存了

Hibernate(六)一对多映射(多对一)的更多相关文章

  1. 一口一口吃掉Hibernate(六)——多对多关联映射

    今天来说说hibernate中的多对多关联映射,多对多关联映射涉及到单向映射和双向映射2种. 首先举个多对多关联例子:用户User和角色Role,一个用户可以属于多个角色,一个角色可以有多个用户.这就 ...

  2. hibernate进阶--一对多映射配置

    hibernate作为一款优秀的ORM框架,广受大家喜爱,也被Java社区公认为持久层的首选.虽然jdbc为Java数据库操 作带来了诸多便利,但是并没有统一SQL语句的写法,而且具体操作数据库的代码 ...

  3. Hibernate-ORM:12.Hibernate中的多对多关联关系

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 本篇博客将讲述Hibernate中的多对多关联关系的操作,准备的篇幅较少,望海涵 一,讲述多对多 多对多的关联 ...

  4. Hibernate中双向多对多的两种配置方式

    Hibernate中双向多对多的两种配置方式 1.建立多对多双向关联关系 package cn.happy.entitys; import java.util.HashSet; import java ...

  5. Hibernate ManyToOne Mappings 多对一关联映射

    Hibernate ManyToOne Mappings 多对一关联映射 Hibernate框架的使用步骤: 1.创建Hibernate的配置文件(hibernate.cfg.xml)2.创建持久化类 ...

  6. hibernate关联关系(多对多)

    数据库的多对多数据库中不能直接映射多对多 处理:创建一个桥接表(中间表),将一个多对多关系转换成两个一对多 注:数据库多表联接查询 永远就是二个表的联接查询 注2:交叉连接 注3:外连接:left(左 ...

  7. Hibernate(六)——多对多关联映射

    前面几篇文章已经较讲解了三大种关联映射,多对多映射就非常简单了,不过出于对关联映射完整性的考虑,本文还是会简要介绍下多对多关联映射. 1.单向多对多关联映射 情景:一个用户可以有多个角色,比如数据录入 ...

  8. --------------Hibernate学习(四) 多对一映射 和 一对多映射

    现实中有很多场景需要用到多对一或者一对多,比如上面这两个类图所展现出来的,一般情况下,一个部门会有多名员工,一名员工只在一个部门任职. 多对一关联映射 在上面的场景中,对于Employee来说,它跟D ...

  9. hibernate之一对多映射

    目录 第一章 课程简介 第二章 Hibernate中的单向一对多关联 2-1 一对多映射简介 2-2 hibernate的基础配置 2-3 创建HibernateUtil工具类 2-4 在mysql数 ...

随机推荐

  1. ng-show和ng-if的区别

    第一点区别是, ng-if 在后面表达式为 true 的时候才创建这个 dom 节点, ng-show 是初始时就创建了,用display:block 和 display:none 来控制显示和不显示 ...

  2. MySql篇

    CentOS6下通过yum安装的MySQL是5.1版的,比较老,所以就想通过源代码安装高版本的5.6.26. 一:卸载旧版本 使用下面的命令检查是否安装有MySQL Server rpm -qa | ...

  3. 计算机音频基础-PCM简介

    我们在音频处理的时候经常会接触到PCM数据:它是模拟音频信号经模数转换(A/D变换)直接形成的二进制序列,该文件没有附加的文件头和文件结束标志. 声音本身是模拟信号,而计算机只能识别数字信号,要在计算 ...

  4. Tasker to detect application running in background

    We used to be told that tasker is only capable of detecting foreground application, if the app gets ...

  5. 网络编程_Python-网络模型.

    http://xmdevops.blog.51cto.com/11144840/1861280

  6. Lambda与委托

    Lambda 表达式是一个可用于创建委托或表达式树类型的匿名函数. 通过使用 lambda 表达式,可以可作为参数 或 返回为函数调用值的本地函数.Lambda 表达式对于编写 LINQ 查询表达式特 ...

  7. maven生命周期(lifecycle)—— maven权威指南学习笔记(四)

    定义: 生命周期是包含在一个项目构建中的一系列有序的阶段 举个例子来说就是maven 对一个工程进行: 验证(validate) …… 编译源码(compile) …… 编译测试源码(test-com ...

  8. scala编程第18章学习笔记——有状态的对象

    银行账号的简化实现: scala> class BankAccount{ | private var bal: Int = 0 | def balance: Int = bal | def de ...

  9. OpenCV 脸部跟踪(1)

        本文中的知识来自于Mastering  opencv with practical computer vision project一书.     本文实施的脸部跟踪算法都是基于数据驱动的,主要 ...

  10. 安全开发 | 如何让Django框架中的CSRF_Token的值每次请求都不一样

    前言 用过Django 进行开发的同学都知道,Django框架天然支持对CSRF攻击的防护,因为其内置了一个名为CsrfViewMiddleware的中间件,其基于Cookie方式的防护原理,相比基于 ...