Hibernatel框架关联映射

Hibernate程序执行流程:

1.集合映射

需求:网络购物时,用户购买商品,填写地址
每个用户会有不确定的地址数目,或者只有一个或者有很多。这个时候不能把每条地址分别放在一个字段,这样的话会非常的麻烦。

数据库设计:创建两个表,一个是保存用户信息,一个表保用户的地址。使用外键引用。javaBean对象中的地址信息使用Set集合方式。配置映射使集合能够映射到数据库

1.1.集合映射的配置和保存

集合分为Set,List,Map集合,也有数组可用,使用方法大体上是相同的,区别只是在映射配置的时候有细微的区别。下面是javaBean对象和集合映射的配置写法,以及测试类。

JavaBean对象:


/*** User对象*/
public class User {private int userId;private String userName;//一个用户,对应的多个地址private Set<String> address;private List<String> addressList = new ArrayList<String>();
//    private String[] addressArray;//映射方式和List一样,配置的名字换成<array name=""/>private Map<String,String> addressMap = new HashMap<String, String>();//set方法和get方法省略
}

映射文件的写法:
映射文件我在主文件配置了自动创建表,所以不用单独创建表了

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="a_collection"><!--javabean和表的映射--><class name="User" table="t_user"><!--1.主键映射--><id name="userId" column="id"><generator class="native"/></id><!--2.普通字段映射--><property name="userName"/><!--3.set集合属性映射name:指定要映射的set集合的属性table:集合属性要映射到的表key:指定集合表(t_address)的外键字段element:指定集合表的其他字段type:元素类型,一定要指定--><set name="address" table="t_address"><key column="uid"/><element column="address" type="string"/></set><!--List集合映射list-index:指定的是拍序列名称,因为要保证list集合的有序--><list name="addressList" table="t_addressList"><key column="uid"/><list-index column="idx"/><element column="address" type="string"/></list><!--Map集合的映射key:外键字段map-key:指定Map的keyelement:指定map的value--><map name="addressMap" table="t_addressMap"><key column="uid"/><map-key type="string" column="shortName"/><element column="address" type="string"/></map></class>
</hibernate-mapping>

测试类:

package a_collection;import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import org.junit.Test;import java.util.HashSet;
import java.util.Set;/***集合映射的测试类*/
public class App {private static SessionFactory sf;static {sf = new Configuration().configure().buildSessionFactory();}//保存Set@Testpublic void testSaveSet() throws Exception{Session session = sf.openSession();session.beginTransaction();//--保存adressSet<String> addressSet = new HashSet<String>();addressSet.add("广州");addressSet.add("深圳");//用户对象User user = new User();user.setUserName("Jack");user.setAddress(addressSet);//保存到数据库session.save(user);session.getTransaction().commit();session.close();}//保存List/Map@Testpublic void testSaveList() throws Exception{Session session = sf.openSession();session.beginTransaction();//用户对象User user = new User();user.setUserName("Jack");user.getAddressList().add("广州");user.getAddressList().add("深圳");//保存到数据库session.save(user);session.getTransaction().commit();session.close();}//保存Map@Testpublic void testSaveMap() throws Exception{Session session = sf.openSession();session.beginTransaction();//用户对象User user = new User();user.setUserName("Tom");user.getAddressMap().put("A001","广州");user.getAddressMap().put("A002","深圳");//保存到数据库session.save(user);session.getTransaction().commit();session.close();}}

1.2.集合数据的获取

/*** 集合数据的获取*/
public class App02 {private static SessionFactory sf;static {sf = new Configuration().configure().buildSessionFactory();}//获取@Testpublic void testGet() throws Exception{Session session = sf.openSession();session.beginTransaction();//获取user对象,因为User中有set,list,map属性,所有会全部查询出来User user = (User)session.get(User.class, 3);//及时加载//查询用户,同时可以获取用  户关联的set,list,map集合的数据,因为有正确映射//当使用到集合数据的时候,才向数据库发送执行的sql语句(懒加载)System.out.println(user);session.getTransaction().commit();session.close();}
}

集合映射中,映射的集合元素,都是普通的类型,但是能不能为对象呢?这个时候就可以使用一对多或者多对一。

2.一对多或多对一映射(重点)

2.1.逻辑分析

需求:部门和员工的关系:
一个部门有多个员工--一对多
多个员工,属于同一个部门--多对一

数据库:有两个表,一个是员工表(id,姓名,薪水,部门外键),一个是部门表(id,部门名称),员工表中有部门表的外键。

JavaBean设计:要有两个对象,一个员工一个部门,是两个对象。

映射:
为了将数据库和JavaBean映射起来,映射配置中如果是配置一方,就只能通过一方维护到另外一方,如果要两方都能维护到另外一方,需要两方都能配置。

2.2.代码实现

创建两个JavaBean对象,一个是员工,一个是部门

/*** 员工方对象*/
public class Employee {private int empId;private String empName;private double salary;//员工与部门[多对一]private Dept dept;//省略get和set}
/*** 部门方对象*/
public class Dept {private int depId;private String deptName;//部门对应多个员工[一对多]private Set<Employee> emps = new HashSet<Employee>();//省略get和set}

对两个JavaBean对象分别进行映射:
Employee对象的映射:Employee.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="b_oneToMany"><class name="Employee" table="t_employee"><id name="empId"><generator class="native"/></id><property name="empName" length="20"/><property name="salary" type="double"/><!--多对一关联映射配置(员工管理到部门)1.映射的部门属性:name="dept"2.映射的部门对象,对应的外键字段:column="dept_id"3.部门的类型:class="Dept"--><many-to-one name="dept" column="dept_id" class="Dept"/></class>
</hibernate-mapping>

Dept的映射:Dept.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="b_oneToMany"><class name="Dept" table="t_dept"><id name="depId"><generator class="native"/></id><property name="deptName" length="20"/><!--一对多关联映射配置(通过部门管理到员工)1.指定映射的集合属性:name="emps"2.集合属性对应的集合表:table="t_employee"3.集合表的外键字段:<key column="deptId"/>4.集合元素的类型:<one-to-many class="Employee"/>--><set name="emps" table="t_employee"><key column="dept_id"/><one-to-many class="Employee"/></set></class>
</hibernate-mapping>

测试类,分别从一的一方(Dept)来操作,使可以同时更新Employee;也测试从多的一方(Employee)来操作,使可以同时更新Dept

package b_oneToMany;import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import org.junit.Test;/*** 测试类,分别从两个对象来维护表*/
public class App {private static SessionFactory sf;static {sf = new Configuration().configure().buildSessionFactory();}//保存,部门方维护(一的一方操作)@Testpublic void save(){Session session = sf.openSession();session.beginTransaction();//部门对象Dept dept = new Dept();dept.setDeptName("应用开发部");//员工对象Employee emp_zs = new Employee();emp_zs.setEmpName("张三");Employee emp_ls = new Employee();emp_ls.setEmpName("李四");//处理关系dept.getEmps().add(emp_zs);dept.getEmps().add(emp_ls);session.save(emp_zs);session.save(emp_ls);session.save(dept);//保存部门,部门下所有的员工session.getTransaction().commit();session.close();}//【推荐】保存,员工方维护(多的一方操作)@Testpublic void save2(){Session session = sf.openSession();session.beginTransaction();//部门对象Dept dept = new Dept();dept.setDeptName("人事部");//员工对象Employee emp_zs = new Employee();emp_zs.setEmpName("张三");Employee emp_ls = new Employee();emp_ls.setEmpName("李四");//处理关系emp_zs.setDept(dept);emp_ls.setDept(dept);session.save(dept);session.save(emp_zs);session.save(emp_ls);session.getTransaction().commit();session.close();}
}

数据的获取:

package b_oneToMany;import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import org.junit.Test;/*** 获取数据*/
public class appGet {private static SessionFactory sf;static {sf = new Configuration().configure().buildSessionFactory();}//保存,部门方维护(一的一方操作)@Testpublic void get(){Session session = sf.openSession();session.beginTransaction();//通过部门方,获取另外一方Dept dept = (Dept)session.get(Dept.class, 1);System.out.println(dept.getDeptName());System.out.println(dept.getEmps());//        //通过员工方,获取另一方Employee emp = (Employee) session.get(Employee.class, 1);System.out.println(emp.getEmpName());System.out.println(emp.getDept().getDeptName());session.getTransaction().commit();session.close();}
}

总结:
在一对多与多对一的关联关系中,保存数据最好的是通过多的一方来维护关系,这样可以减少update语句的生成,从而提高Hibernate的执行效率!

配置一对多与多对一,这种叫:双向关联
只配置一对多,叫单项一对多
只配置多对一,叫单项多对一。

注意:
配置了哪一方,哪一方才有维护关联关系的权限!

3.inverse/cascade

3.1.Inverse属性

Inverse属性是在维护表之间的关联关系的时候起作用的,表示控制权是否转移,在一的一方起作用。比如在一对多的两张表中,如果更改了一个表中的主键或者删除了一个数据,那么另外一张表该如何处理呢。

Inverse的英文意思就是翻转
Inverse=false:不转账,当前方有控制权
Inverse=true:控制反转,当前方没有控制权

Inverse维护表之间的关联关系,主要从以下几个方面来维护:
1.保存数据
有影响。如果设置控制反转,即Inverse=true,然后通过部门方(一的一方)维护关联关系。在保存部门的时候,同时保存员工,数据会保存,但是关联关系不会维护,即员工表中的部门外键不会更新,为NULL。

2.获取数据
没有影响。

3.解除关联关系
有影响
Inverse=false:可以解除关联
Inverse=true:当前方(部门)没有控制权,不能接触关联

4.删除数据对关联关系的影响
有影响
Inverse=false:有控制权,可以删除。先清空外键作用,再删除数据
Inverse=true:没有控制权,如果删除的记录有被外键引用,会报错,违反主键引用约束!如果删除的记录没有被引用,可以直接删除。

3.2.CasCade属性

CasCade表示级联操作,可以设置到一的一方或多的一方。
CasCade的参数:
none:不级联操作,默认值
save-update:级联保存或更新
delete:级联删除
save-update,delete.级联保存,更新,删除
all :同上,级联保存,更新,删除

4.多对多映射

4.1.多对多映射配置

需求:项目(Project)与开发人员(Developer)
一个项目,有多个开发人员
一个开发人员,参与多个项目!--多对多

例子:
项目1:电商系统,参与的开发人员:曹吉,王春;
项目2:OA系统,王春,老张
例子中有两个项目,开发人员王春同时参与了两个项目。
这个例子中,项目与开发人员就是多对多的关系。

数据库设计:

数据库设计如上,分析:
DB设计:数据库有项目表(t_project),包含id,项目名,日期字段。员工表(t_developer),包含id,员工姓名。这两个表是多对多的关系,一般会有个中间表(t_relation),分别填写两张表的外键,使其联系起来。中间表跟其他两个表之间的关系是一对多的关系

JavaBean:两个对象,分别是项目和开发者。项目中要有开发者的集合对象。开发者中也要有项目的集合对象。

映射:映射的配置要注意一些关键点

代码实现
首先是JavaBean对象,有两个,项目(Project)和开发者员工(Developer)

/*** 项目*/
public class Project {private int prj_id;private String prj_name;//项目下的多个员工private Set<Developer> developers = new HashSet<Developer>();//省略get和set}
/*** 开发人员*/
public class Developer {private int d_id;private String d_name;//开发者参数的多个项目private Set<Project> projects = new HashSet<Project>();//省略get和set}

然后是映射的配置,因为有两个JavaBean对象,所有也需要有两个映射文件
Project.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="c_many2many"><class name="Project" table="t_project"><id name="prj_id"><generator class="native"/></id><property name="prj_name" length="20"/><!--多对多映射:1.映射的集合属性:name="developers"2.集合属性,对应的中间表:table="t_relation"3.在中间表中的外键字段:<key column="prjId"/>4.3中的外键字段对应的中间表字段:column="did"5.集合属性元素的类型:class="Developer"--><set name="developers" table="t_relation"><key column="prjId"/><many-to-many column="did" class="Developer"/></set></class>
</hibernate-mapping>

Developer.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="c_many2many"><class name="Developer" table="t_developer"><id name="d_id"><generator class="native"/></id><property name="d_name" length="20"/><!--多对多映射:员工方name:指定映射的集合属性table:集合属性对应的中间表key:指定中间表的外键字段(引用当前表t_developer主键的外键字段)many-to-many:column:指定外键字段对应的项目字段class:集合元素的类型--><set name="projects" table="t_relation"><key column="did"/><many-to-many column="prjId" class="Project"/></set></class>
</hibernate-mapping>

测试类:

package c_many2many;import b_oneToMany.Dept;
import b_oneToMany.Employee;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import org.junit.Test;/*** 测试类*/
public class App {private static SessionFactory sf;static {sf = new Configuration().configure().buildSessionFactory();}//多对多数据保存@Testpublic void save(){Session session = sf.openSession();session.beginTransaction();/*模拟数据:电商系统(曹吉,王春)OA系统(王春,老张)*///创建项目对象Project prj_ds = new Project();prj_ds.setPrj_name("电商系统");Project prj_oa = new Project();prj_oa.setPrj_name("OA系统");//创建开发者对象Developer dev_cj = new Developer();dev_cj.setD_name("曹吉");Developer dev_wc = new Developer();dev_wc.setD_name("王春");Developer dev_lz = new Developer();dev_lz.setD_name("老张");//关系【项目方操作】prj_ds.getDevelopers().add(dev_cj);prj_ds.getDevelopers().add(dev_wc);//电商系统:曹吉,王春prj_oa.getDevelopers().add(dev_wc);prj_oa.getDevelopers().add(dev_lz);//OA系统:王春,老张//        //关系【开发者方】
//        //注意可以在项目方维护员工方,也可以通过员工方维护项目方,不用在两方同时维护,只需要维护一方就可以了
//        dev_cj.getProjects().add(prj_ds);
//        dev_wc.getProjects().add(prj_ds);
//        dev_wc.getProjects().add(prj_oa);
//        dev_lz.getProjects().add(prj_oa);//保存session.save(prj_ds);session.save(prj_oa);//使用级联映射保存,在项目方维护时,员工方就不需要再写保存//级联必须设置:cascade="save-update"
//        session.save(dev_cj);
//        session.save(dev_wc);
//        session.save(dev_lz);session.getTransaction().commit();session.close();}@Testpublic void bak(){Session session = sf.openSession();session.beginTransaction();session.getTransaction().commit();session.close();}
}

4.2.多对多关联关系的维护

关联关系一般只需要在一方进行维护,不用在两方都设置。
设置Inverse属性,在多对多中维护关联关系的影响?
其实多对多中和一对多和多对一的功作用是相同的。
1.保存数据
有影响
Inverse=false,有控制权,可以维护关联关系,保存数据的时候会把对象关系插入中间表
Inverse=true 没有控制权,不会往中间表插入数据

2.获取数据
无影响

3.解除关系
有影响:
Inverse=false:有控制权,解除关系就是删除中间表的数据
Inverse=true:没有控制权,不能解除关系

4.删除数据
有影响:
Inverse=false:有控制权,先删除中间表数据,再删除自身
Inverse=true:没有控制权,如果删除的数据有被引用,会报错!否则,才可以删除

转载于:https://www.cnblogs.com/cenyu/p/6260162.html

Hibernatel框架关联映射相关推荐

  1. Java三大框架之——Hibernate关联映射与级联操作

    什么是Hibernate中的关联映射? 简单来说Hibernate是ORM映射的持久层框架,全称是(Object Relational Mapping),即对象关系映射. 它将数据库中的表映射成对应的 ...

  2. (转)MyBatis框架的学习(五)——一对一关联映射和一对多关联映射

    http://blog.csdn.net/yerenyuan_pku/article/details/71894172 在实际开发中我们不可能只是对单表进行操作,必然要操作多表,本文就来讲解多表操作中 ...

  3. 【Hibernate框架】关联映射(多对多关联映射)

    按着我们的总结行进计划,接下来,就是有关于多对多映射的总结了. 我们来举个例子啊,很长时间以来,房价暴涨不落,但是还有很多人拥有很多套房产,假如说,一个富豪拥有九套房产,家里人么准去住哪一套,我们就以 ...

  4. 关联映射 一对多 实验心得_使用影响映射来帮助您的团队进行实验

    关联映射 一对多 实验心得 影响映射是一种在领导者和项目团队之间建立共识的技术. 影响图以引人入胜的研讨会形式提供,是以鼓励创新的方式启动工作流的理想方式. Gojko Adzic首次在2011年的小 ...

  5. (转)Hibernate关联映射——对象的三种关系

    http://blog.csdn.net/yerenyuan_pku/article/details/70148618 Hibernate关联映射--对象的三种关系 Hibernate框架基于ORM设 ...

  6. 三分钟带你了解mybatis关联映射(案例分析一对一,多对多)

    ------------------------------------------------原创不易,如若喜欢,请点一点赞吧!----------------------------------- ...

  7. MyBatis关联映射例题

    在确保可运行项目能够正确无误地运行之后,再严格照着教程的步骤,对代码模仿一遍.模仿过程难免代码有出入,导致无法得到期望的运行结果,此时此刻通过比较正确答案 ( 可运行项目 ) 和自己的代码,来定位问题 ...

  8. mybatis手写多对多关联映射

    mybatis手写多对多关联映射 1.一对一关联查询 1.1resultType实现 1.2resultMap实现 2.一对多关联查询 3.多对多关联查询 4.resultType与resultMap ...

  9. 04ssm_Mybaits关联映射和缓存机制

    04ssm_Mybaits关联映射和缓存机制 文章目录 04ssm_Mybaits关联映射和缓存机制 一.关联映射概述 1.数据表的三种关联映射关系 2.Java描述数据表的关联映射关系 3.本单元实 ...

最新文章

  1. Dubbo -- 系统学习 笔记 -- 示例 -- 参数验证
  2. C#最受欢迎功能 -- C#1至C#7
  3. 解决GitHub未配置SSH key提示错误信息
  4. 【大话数据结构算法】快速排序算法
  5. C语言 数据结构 栈(用链表实现)
  6. h.264 视频解码的一点小经验(ffmpeg)
  7. [翻译] ABCIntroView
  8. 英文站变现赚美金的7种方式
  9. 2021微信网页跳转APP
  10. Keil5 平台 S3C2440裸机程序开发环境配置
  11. 被认为是世界史上50个最伟大的发明有哪些?
  12. python_爬校花图片
  13. m低信噪比下GPS信号的捕获算法研究,使用matlab算法进行仿真
  14. SQL Server 2005无日志文件附加数据库
  15. STM32学习笔记1(初识STM32)
  16. PHP 记录访客的浏览信息
  17. 【实习小tip】多层dialog弹窗遮罩问题、elementUI的form表单组件的select框在只读的情况下没办法拿到传来的数据、从弹窗子组件获取数据后需要刷新页面
  18. 国家为什么会失败-读书笔记
  19. 计算机网络路由器作用是什么,路由器的作用是什么?
  20. 计算机课程实验教学案例,联席会|第四届全国计算机类课程实验教学案例设计竞赛|...

热门文章

  1. java斗地主怎么出牌_斗地主滑动选牌出牌(Cocos Creator)
  2. matlab warp,matlab warpimg
  3. win10安装ubuntu子系统,然后安装python3.6
  4. Java多态形式_Java多态
  5. ssm oracle mysql_ssm连接oracle数据库
  6. 23.1解析函数的级数表示(二)
  7. LeafGAN:一种有效的实用植物病害诊断数据扩充方法
  8. 可视化类激活的热力图
  9. linux修改端口监听地址,修改nginx/Tomcat等Web服务的端口监听地址
  10. 2016-2018年机器学习大赛TOP开源作品汇总