03_Hibernate关系映射
关系映射?
Hibernate的主要目的就是JAVA程序员可以随心所欲的使用对象编程思维来操作数据库。一些数据库表的关系我们应该可以通过hibernate实现,比如数据库中用到的主外键关系,还有一些与主外键关系的设置,比如主键的信息被删除,外键关联的信息也要删除等,所以hibernate同样应该实现这种映射关系。
系统设计中的三种实体关系
数据库实体表之间的关系映射
一对多:客户(customers)和订单(orders)的关系
一般在多的一方添加外键
一对一:公司(company)和公司地址(address)的关系
在任意一方添加对方的主键作为外键
多对多:订单(orders)和商品(products)数据表
关系上升为第三张表,分别引入双方的主键作为外键
Hibernate关联映射
hibernate的一对多关联映射又分为两种实现方式:
单项关联:立从employee到department的多对一关联,或者仅仅建立从department到employee的一对多关联。
双项关联:既建立从employee到department的多对一关联,又建立从department到employee的一对多关联。
1.单向多对一
员工emp和部门dept,
规则:在多的一方配置,多的一方要封装一个(一的一方)属性
name:是一的一方的属性名 , column:外键 列名 class:one的类的全路径
<many-to-one name="dept" column="deptid" class="com.manytoone.Dept" not-null="false" cascade="all">
</many-to-one>
Emp.java
public class Emp {
private Integer eid;
private String ename;
private Dept dept;
public Integer getEid() {
return eid;
}
public void setEid(Integer eid) {
this.eid = eid;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
}
Emp.hbm.xml
<?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="com.manytoone.Emp" table="emp">
<id name="eid" column="eid" type="java.lang.Integer" length="10">
<!--主键生成策略-->
<generator class="increment">
</generator>
</id>
<!--ename属性-->
<property name="ename" column="ename" type="java.lang.String" length="50">
</property>
<!--name:属性名 column:外键 class: 与name属性的全路径 cascade:表示会影响所关联的的表-->
<many-to-one name="dept" column="deptid" class="com.manytoone.Dept" not-null="false" cascade="save-update">
</many-to-one>
</class>
</hibernate-mapping>
Dept.java
public class Dept {
private Integer did;
private String dname;
public Integer getDid() {
return did;
}
public void setDid(Integer did) {
this.did = did;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
}
dept.hbm.xml
<?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="com.manytoone.Dept" table="dept">
<id name="did" column="did" type="java.lang.Integer" length="10">
<!--主键生成策略-->
<generator class="increment">
</generator>
</id>
<!--dname属性-->
<property name="dname" column="dname" type="java.lang.String" length="50">
</property>
</class>
</hibernate-mapping>
2.单向一对多关联
dept->emp(单向一对多)
规则:在一的一方配置,要封装一个set集合.
<!-- name属性:表示一的一方set集合的属性, table: 多的一方的表名 -->
<set name="emps" table="emp" cascade="all">
<key>
<!-- 外键 -->
<column name="deptid"></column>
</key>
<!-- class: many方的全类名 -->
<one-to-many class="Emp"/>
</set>
dept.java
public class Dept {
private Integer did;
private String dname;
private Set<Emp> emps = new HashSet<Emp>();
public Integer getDid() {
return did;
}
public void setDid(Integer did) {
this.did = did;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public Set<Emp> getEmps() {
return emps;
}
public void setEmps(Set<Emp> emps) {
this.emps = emps;
}
}
Dept.hbm.xml
<?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="com.onetomany.Dept" table="dept" lazy="true">
<id name="did" column="did" type="java.lang.Integer" length="10">
<!--主键生成策略-->
<generator class="increment">
</generator>
</id>
<!--dname属性-->
<property name="dname" column="dname" type="java.lang.String" length="50">
</property>
<!--关联级别及时加载,查询时会把关联的也会查询出来-->
<set name="emps" table="emp" cascade="all" lazy="true">
<key>
<column name="deptid"></column> <!--外键-->
</key>
<one-to-many class="com.onetomany.Emp"/><!--外键关联的类-->
</set>
</class>
</hibernate-mapping>
Emp.java
public class Emp {
private Integer eid;
private String ename;
private Integer deptid;
public Integer getEid() {
return eid;
}
public void setEid(Integer eid) {
this.eid = eid;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public Integer getDeptid() {
return deptid;
}
public void setDeptid(Integer deptid) {
this.deptid = deptid;
}
}
Emp.hbm.xml
<?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="com.onetomany.Emp" table="emp">
<id name="eid" column="eid" type="java.lang.Integer" length="10">
<!--主键生成策略-->
<generator class="increment">
</generator>
</id>
<!--ename属性-->
<property name="ename" column="ename" type="java.lang.String" length="50">
</property>
<property name="deptid" column="deptid" type="java.lang.Integer" length="10">
</property>
</class>
</hibernate-mapping>
3.双向一对多*
dept->Emp
规则:1.在多的一方配置,多的一方要封装一个(一的一方)属性
2.在一的一方配置,要封装一个set集合.
上述两个配置综合
Dept.java
public class Dept {
private Integer did;
private String dname;
private Set<Emp> emps = new HashSet<Emp>();
public Integer getDid() {
return did;
}
public void setDid(Integer did) {
this.did = did;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public Set<Emp> getEmps() {
return emps;
}
public void setEmps(Set<Emp> emps) {
this.emps = emps;
}
}
Dept.hbm.xml
<?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="com.doubleonetomany.Dept" table="dept">
<id name="did" column="did" type="java.lang.Integer" length="10">
<!--主键生成策略-->
<generator class="increment">
</generator>
</id>
<!--dname属性-->
<property name="dname" column="dname" type="java.lang.String" length="50">
</property>
<set name="emps" table="emp" cascade="all">
<key>
<column name="deptid"></column> <!--外键-->
</key>
<one-to-many class="com.doubleonetomany.Emp"/><!--外键关联的类-->
</set>
</class>
</hibernate-mapping>
Emp.java
public class Emp {
private Integer eid;
private String ename;
private Dept dept;
public Integer getEid() {
return eid;
}
public void setEid(Integer eid) {
this.eid = eid;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
}
Emp.hbn.xml
<?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="com.icss.doubleonetomany.Emp" table="emp">
<id name="eid" column="eid" type="java.lang.Integer" length="10">
<!--主键生成策略-->
<generator class="increment">
</generator>
</id>
<!--ename属性-->
<property name="ename" column="ename" type="java.lang.String" length="50">
</property>
<!--name:属性名 column:外键 class: 与name属性的全路径 cascade:表示会影响所关联的的表-->
<many-to-one name="dept" column="deptid" class="com.icss.doubleonetomany.Dept" not-null="false">
</many-to-one>
</class>
</hibernate-mapping>
4.双向一对一
employee->joinpart 员工和入党申请书
规则:在实体类中分别要定义对方类型的属性
在有外键一方配置 :<many-to-one name="joinpart" column="joinpart_id" class="JoinPart" cascade="save-update"></many-to-one>
在没有外键的一方配置 :<one-to-one name="emp" class="Employee" property-ref="joinpart"></one-to-one>
注:property-ref:对方封装的相关类型的属性
Employee.java
package com.icss.doubleonetoone;
import java.util.Date;
/**
* Created by jiatp on 2019/8/2.
*/
public class Employee {
private Integer eid;
private String name;
private Date birthday;
private JoinPart joinPart;
public JoinPart getJoinPart() {
return joinPart;
}
public void setJoinPart(JoinPart joinPart) {
this.joinPart = joinPart;
}
public Integer getEid() {
return eid;
}
public void setEid(Integer eid) {
this.eid = eid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
Employee.hbm.java
<?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="com.doubleonetoone.Employee" table="employee">
<id name="eid" column="eid" type="java.lang.Integer" length="10">
<generator class="increment"/>
</id>
<property name="name" column="name" type="java.lang.String" length="50">
</property>
<property name="birthday" column="birthday" type="java.util.Date">
</property>
<many-to-one name="joinPart" column="joinPart_id" class="com.doubleonetoone.JoinPart" cascade="save-update"></many-to-one>
</class>
</hibernate-mapping>
JoinPart.java
public class JoinPart {
private Integer jid;
private Date joindate;
private Employee emp;
public Integer getJid() {
return jid;
}
public void setJid(Integer jid) {
this.jid = jid;
}
public Date getJoindate() {
return joindate;
}
public void setJoindate(Date joindate) {
this.joindate = joindate;
}
public Employee getEmp() {
return emp;
}
public void setEmp(Employee emp) {
this.emp = emp;
}
}
JoinPart.hbm.xml
<?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="com.icss.doubleonetoone.JoinPart" table="joinPart">
<id name="jid" column="jid" type="java.lang.Integer" length="10">
<generator class="increment"/>
</id>
<property name="joindate" column="joindate" type="java.util.Date">
</property>
<one-to-one name="emp" class="com.doubleonetoone.Employee" property-ref="joinPart"></one-to-one>
</class>
</hibernate-mapping>
5.双向多对多
User->Role 用户和角色
规则:双向多对多
处理中间表,在中间表中存放它们的外键
name:集合类型的属性名 table:中间表的表名 column: 中间与之对应的外键
class : 后面many方的类的全路径 column: 后面many类对应中间表的外键
<set name="users" table="sys_role_user">
<key column="r_id"></key>
<many-to-many class="User" column="u_id"></many-to-many>
</set>
User.java
public class User {
private Integer uid;
private String name;
private Set<Role> roles = new HashSet<Role>(); //双向多对多
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
User.hbm.xml
<?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="com.doublemanytomany.User" table="user">
<id name="uid" column="uid" type="java.lang.Integer" length="10">
<!--主键生成策略-->
<generator class="increment">
</generator>
</id>
<property name="name" column="name" length="50" type="java.lang.String">
</property>
<!--inverses属性;true关联维护时将控制权交给对方-->
<set name="roles" table="sys_role_user" inverse="true">
<key column="u_id">
</key>
<many-to-many class="com.doublemanytomany.Role" column="r_id">
</many-to-many>
</set>
</class>
</hibernate-mapping>
Role.java
public class Role {
private Integer rid;
private String name;
private Set<User> users = new HashSet<User>(); //多对多
public Integer getRid() {
return rid;
}
public void setRid(Integer rid) {
this.rid = rid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
}
Role.hbm.xml
<?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="com.doublemanytomany.Role" table="role">
<id name="rid" column="rid" type="java.lang.Integer" length="10">
<!--主键生成策略-->
<generator class="increment">
</generator>
</id>
<property name="name" type="java.lang.String" column="name" length="50">
</property>
<set name="users" table="sys_role_user">
<key column="r_id">
</key>
<many-to-many class="com.doublemanytomany.User" column="u_id">
</many-to-many>
</set>
</class>
</hibernate-mapping>
注意:对于双向 n-n 关联, 须把其中一端的 inverse 设置为 true, 否则可能会造成主键冲突.
测试
/**
* Description:测试双向多对多关联
* User:jiatp
* Date: 2019/8/3 18:14
*/
public class doublemanytomanyTest {
@Test
public void test(){
Session session = HibernateUtils.openSession();
Transaction ts = session.beginTransaction();
//创建用户
User user1 = new User();
user1.setName("jtp");
// 创建角色
Role role = new Role();
role.setName("CEO");
//关联关系
user1.getRoles().add(role);
role.getUsers().add(user1);
session.save(user1);
session.save(role);
ts.commit();
session.close();
}
}
只举例双向对多的例子,其余的自行测试。
03_Hibernate关系映射的更多相关文章
- 问题记录:EntityFramework 一对一关系映射
EntityFramework 一对一关系映射有很多种,比如主键作为关联,配置比较简单,示例代码: public class Teacher { public int Id { get; set; } ...
- 死去活来,而不变质:Domain Model(领域模型) 和 EntityFramework 如何正确进行对象关系映射?
写在前面 阅读目录: 设计误区 数据库已死 枚举映射 关联映射 后记 在上一篇<一缕阳光:DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)?>博文中, ...
- 解析大型.NET ERP系统数据访问 对象关系映射框架LLBL Gen Pro
LLBL Gen Pro是一个为.NET开发人员设计的的对象关系映射(ORM)框架,与NHibernate,Entity Framework等框架一样,通过实体与数据表的映射,实现关系数据库持久化. ...
- hibernate学习四(关系映射一对一与组件映射)
一.关系映射简介 在数据库中,表与表的关系,仅有外键.但使用hibernate后,为面向对象的编程,对象与对象的关系多样化:如 一对一,一对多,多对多,并具有单向和双向之分. 开始练习前,复制上一次项 ...
- Entity Framework Code First关系映射约定
本篇随笔目录: 1.外键列名默认约定 2.一对多关系 3.一对一关系 4.多对多关系 5.一对多自反关系 6.多对多自反关系 在关系数据库中,不同表之间往往不是全部都单独存在,而是相互存在关联的.两个 ...
- Mybatis框架中实现双向一对多关系映射
学习过Hibernate框架的伙伴们很容易就能简单的配置各种映射关系(Hibernate框架的映射关系在我的blogs中也有详细的讲解),但是在Mybatis框架中我们又如何去实现 一对多的关系映射呢 ...
- hibernate(3) —— 关系映射
hibernate中关系映射指的是实体类与实体类间的关系.和数据库中表与表之间的关系类似,有一对一,多对一,一对多,多对多四种映射关系. 一:一对一映射 两个对象之间是一对一的关系,如人和身份证之间是 ...
- OrchardNoCMS实体关系映射扩展
在OrchardNoCMS中,默认的系统会把实体关系映射保存到mappings.bin文件中. 如果不进行任何修改,默认的可以自动保存关系映射的model是有很大限制的. 条件是model的命名空间必 ...
- 【Java EE 学习 46】【Hibernate学习第三天】【多对多关系映射】
一.多对多关系概述 以学生和课程之间的关系为例. 1.在多对多关系中涉及到的表有三张,两张实体表,一张专门用于维护关系的表. 2.多对多关系中两个实体类中应当分别添加对方的Set集合的属性,并提供se ...
随机推荐
- ASP.NET MVC easyUI-datagrid 的当前页合计and总合计
一.HTML代码 <table id="dg" class="easyui-datagrid" style="width: 100%; heig ...
- JAVA数据结构之哈希表
Hash表简介: Hash表是基于数组的,优点是提供快速的插入和查找的操作,编程实现相对容易,缺点是一旦创建就不好扩展,当hash表被基本填满的时候,性能下降非常严重(发生聚集引起的性能的下降),而且 ...
- 校园商铺-4店铺注册功能模块-1Dao层之更新店铺
dao层增加更新店铺的方法 package com.csj2018.o2o.dao; import com.csj2018.o2o.entity.Shop; public interface Shop ...
- JavaScript 数据值校验工具类
/** * 数据值校验工具类 */ var checkService = { // 不校验 none: function () { return true; }, //非空校验 isEmpty: fu ...
- CSS3——2D变形和3D变形
2D变形(CSS3) transform transform是CSS3中具有颠覆性的特征之一,可以实现元素的位移.旋转.倾斜.缩放,甚至支持矩阵方式,配合过渡和即将学习的动画知识,可以取代大量之前只能 ...
- 关于web前端网站优化
不知道是哪位大牛的文章,转过来嘻嘻. 作者:斯迪链接:https://www.zhihu.com/question/21658448/answer/18903129来源:知乎著作权归作者所有.商业转载 ...
- javascript中onclick(this)用法和onclick(this.value)用法介绍
onclick(this.value)代码详解 <html> <head> <script language="javascript"> fun ...
- 纯CSS3实现图片展示特效
本文中要实现的一个纯CSS3的图片展示特效,以前只能用JavaScript实现,可想而知会受到多方面的限制,特别是性能.而今天我们将用简单的CSS3代码实现,你会发现它的动画效果在现代浏览器的帮助下无 ...
- import time 进度条动态输出26个字母
# 2018-08-06 19:42:51 import time # 调用时间模块 num = 97 # 字母a while num <= 115: # print(chr(num), end ...
- svg path命令
参考:https://www.jianshu.com/p/c819ae16d29b https://www.cnblogs.com/guxuelong/p/7743736.html M ...