Hibernate关联关系配置(一对多,一对一,多对多)
一对多
创建两个类 Manager(一这一端) Worker(多这一端) 即一个经理下有多个员工
package com.hibernate.n21;import java.util.HashSet; import java.util.Set;public class Manager {private Integer mgrId;private String mgrName;/** 1. 声明集合类型时, 需使用接口类型, 因为 hibernate 在获取* 集合类型时, 返回的是 Hibernate 内置的集合类型, 而不是 JavaSE 一个标准的* 集合实现. * 2. 需要把集合进行初始化, 可以防止发生空指针异常*/private Set<Worker> workers = new HashSet<>();public Integer getMgrId() {return mgrId;}public void setMgrId(Integer mgrId) {this.mgrId = mgrId;}public String getMgrName() {return mgrName;}public void setMgrName(String mgrName) {this.mgrName = mgrName;}public Set<Worker> getWorkers() {return workers;}public void setWorkers(Set<Worker> workers) {this.workers = workers;}}package com.hibernate.n21;public class Worker {private Integer id;private String name;private Manager manager;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Manager getManager() {return manager;}public void setManager(Manager manager) {this.manager = manager;}@Overridepublic String toString() {return "Worker [id=" + id + ", name=" + name + ", manager=" + manager + "]";}}
xml文件
<!--1这一端--> <?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 2017-8-10 7:47:59 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping><class name="com.hibernate.n21.Manager" table="MANAGER"><id name="mgrId" type="java.lang.Integer"><column name="MGR_ID" /><generator class="native" /></id><property name="mgrName" type="java.lang.String"><column name="MGR_NAME" /></property><!-- 映射 1 对多的那个集合属性 --><!-- set: 映射 set 类型的属性, table: set 中的元素对应的记录放在哪一个数据表中. 该值需要和多对一的多的那个表的名字一致 --><!-- inverse: 指定由哪一方来维护关联关系. 通常设置为 true, 以指定由多的一端来维护关联关系 --><!-- order-by 在查询时对集合中的元素进行排序, order-by 中使用的是表的字段名, 而不是持久化类的属性名 --><set name="workers" table="WORKER" inverse="true"><!-- 执行多的表中的外键列的名字 --><key><column name="MGR_ID" /></key><!-- 指定映射类型 --><one-to-many class="com.hibernate.n21.Worker" /></set></class> </hibernate-mapping>
<!--多这端--> <?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 2017-8-10 7:47:59 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping><class name="com.hibernate.n21.Worker" table="WORKER"><id name="id" type="java.lang.Integer"><column name="ID" /><generator class="native" /></id><property name="name" type="java.lang.String"><column name="NAME" /></property><!-- 映射多对一的关联关系。 使用 many-to-one 来映射多对一的关联关系 name: 多这一端关联的一那一端的属性的名字class: 一那一端的属性对应的类名column: 一端对应的数据表中的外键的名字--><many-to-one name="manager" class="com.hibernate.n21.Manager" fetch="join"><column name="MGR_ID" /></many-to-one></class> </hibernate-mapping>
测试代码
package com.hibernate.n21;import static org.junit.Assert.*;import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.junit.After; import org.junit.Before;public class Test {private SessionFactory sessionFactory;private Session session;private Transaction transaction;@Beforepublic void init(){Configuration configuration = new Configuration().configure();ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();sessionFactory = configuration.buildSessionFactory(serviceRegistry);session = sessionFactory.openSession();transaction = session.beginTransaction();}@Afterpublic void destroy(){transaction.commit();session.close();sessionFactory.close();}@org.junit.Testpublic void test() {fail("Not yet implemented");}@org.junit.Testpublic void testMany2OneGet(){//1. 若查询多的一端的一个对象(Worker), 则默认情况下, 只查询了多的一端的对象,不查询一的一端对象(Manager)Worker worker = (Worker) session.get(Worker.class, 1);System.out.println(worker.getName());System.out.println(worker.getManager().getClass());//session.close();//2. 在需要使用到关联的对象时, 才发送对应的 SQL 语句. /*Manager manager = worker.getManager();System.out.println(manager.getMgrName());*/ //3. 在查询对象时, 由多的一端导航到 1 的一端时, //若此时 session 已被关闭, 会发生 LazyInitializationException 异常//4. 获取 Worker 对象时, 默认情况下, 其关联的 Manager对象是一个代理对象! }@org.junit.Testpublic void testMany2OneSave() {Worker worker = new Worker();worker.setName("worker-1");Worker worker2 = new Worker();worker2.setName("worker-2");Worker worker3 = new Worker();worker3.setName("worker-3");System.out.println(worker);System.out.println(worker2);System.out.println(worker3);Manager manager = new Manager();manager.setMgrName("MMM");//设定关联关系 worker.setManager(manager);worker2.setManager(manager);worker3.setManager(manager);//先插入 1 的一端, 再插入 n 的一端, 只有 INSERT 语句.//反过来插入开始Manner的mgrId未生成会产生update语句 session.save(manager);session.save(worker);session.save(worker2);session.save(worker3);}}
数据库截图
一对一关系外键
Manager 和 Department 一个经理一个部门
package com.hibernate.n21;public class Department {private Integer deptId;private String deptName;private Manager mgr;public Integer getDeptId() {return deptId;}public void setDeptId(Integer deptId) {this.deptId = deptId;}public String getDeptName() {return deptName;}public void setDeptName(String deptName) {this.deptName = deptName;}public Manager getMgr() {return mgr;}public void setMgr(Manager mgr) {this.mgr = mgr;}}package com.hibernate.n21;import java.util.HashSet; import java.util.Set;public class Manager {private Integer mgrId;private String mgrName;/** 1. 声明集合类型时, 需使用接口类型, 因为 hibernate 在获取* 集合类型时, 返回的是 Hibernate 内置的集合类型, 而不是 JavaSE 一个标准的* 集合实现. * 2. 需要把集合进行初始化, 可以防止发生空指针异常*/private Set<Worker> workers = new HashSet<>();private Department dept; //在上面的代码上加了这行public Integer getMgrId() {return mgrId;}public void setMgrId(Integer mgrId) {this.mgrId = mgrId;}public String getMgrName() {return mgrName;}public void setMgrName(String mgrName) {this.mgrName = mgrName;}public Set<Worker> getWorkers() {return workers;}public void setWorkers(Set<Worker> workers) {this.workers = workers;}public Department getDept() {return dept;}public void setDept(Department dept) {this.dept = dept;}}
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 2017-8-10 9:04:21 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping><class name="com.hibernate.n21.Department" table="DEPARTMENT"><id name="deptId" type="java.lang.Integer"><column name="DEPTID" /><generator class="native" /></id><property name="deptName" type="java.lang.String"><column name="DEPTNAME" /></property><!-- 使用 many-to-one 的方式来映射 1-1 关联关系 --><many-to-one name="mgr" class="com.hibernate.n21.Manager" column="MGR_ID" unique="true"></many-to-one></class> </hibernate-mapping>
<?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 2017-8-10 7:47:59 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping><class name="com.hibernate.n21.Manager" table="MANAGER"><id name="mgrId" type="java.lang.Integer"><column name="MGR_ID" /><generator class="native" /></id><property name="mgrName" type="java.lang.String"><column name="MGR_NAME" /></property><!-- 映射 1 对多的那个集合属性 --><!-- set: 映射 set 类型的属性, table: set 中的元素对应的记录放在哪一个数据表中. 该值需要和多对一的多的那个表的名字一致 --><!-- inverse: 指定由哪一方来维护关联关系. 通常设置为 true, 以指定由多的一端来维护关联关系 --><!-- order-by 在查询时对集合中的元素进行排序, order-by 中使用的是表的字段名, 而不是持久化类的属性名 --><set name="workers" table="WORKER" inverse="true"><!-- 执行多的表中的外键列的名字 --><key><column name="MGR_ID" /></key><!-- 指定映射类型 --><one-to-many class="com.hibernate.n21.Worker" /></set><!-- 映射 1-1 的关联关系: 在对应的数据表中已经有外键了, 当前持久化类使用 one-to-one 进行映射 --><!-- 没有外键的一端需要使用one-to-one元素,该元素使用 property-ref 属性指定使用被关联实体主键以外的字段作为关联字段--><!-- 在原来的代码上加上一对一关系 --><one-to-one name="dept" class="com.hibernate.n21.Department"property-ref="mgr"></one-to-one></class> </hibernate-mapping>
Test
@org.junit.Testpublic void testGet(){//1. 默认情况下对关联属性使用懒加载Department dept = (Department) session.get(Department.class, 1);System.out.println(dept.getDeptName()); //2. 会出现懒加载异常的问题. // session.close();//3. 查询 Manager 对象的连接条件应该是 dept.manager_id = mgr.manager_id //而不应该是 dept.dept_id = mgr.manager_id所以在xml文件中加入property-ref="mgr"Manager mgr = dept.getMgr();System.out.println(mgr.getMgrName()); }@org.junit.Testpublic void testSave(){Department department = new Department();department.setDeptName("DEPT-BB");Manager manager = new Manager();manager.setMgrName("MGR-BB");//设定关联关系 department.setMgr(manager);manager.setDept(department);//保存操作//建议先保存没有外键列的那个对象. 这样会减少 UPDATE 语句 session.save(manager);session.save(department);}
基于主键
修改Department的xml即可 (删除Manager xml里的property-ref="mgr")
<?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 2017-8-10 9:04:21 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping><class name="com.hibernate.n21.Department" table="DEPARTMENT"><id name="deptId" type="java.lang.Integer"><column name="DEPT_ID" /><!-- 使用外键的方式来生成当前的主键 --><generator class="foreign"><!-- property 属性指定使用当前持久化类的哪一个属性的主键作为外键 --><param name="property">mgr</param></generator></id><property name="deptName" type="java.lang.String"><column name="DEPTNAME" /></property><!-- 使用 many-to-one 的方式来映射 1-1 关联关系 --><!-- 采用 foreign 主键生成器策略的一端增加 one-to-one 元素映射关联属性,其 one-to-one 节点还应增加 constrained=true 属性, 以使当前的主键上添加外键约束--><one-to-one name="mgr" class="com.hibernate.n21.Manager" constrained="true"></one-to-one></class> </hibernate-mapping>
多对多
public class Category {private Integer id;private String name;private Set<Item> items = new HashSet<>();public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Set<Item> getItems() {return items;}public void setItems(Set<Item> items) {this.items = items;}}public class Item {private Integer id;private String name;private Set<Category> categories = new HashSet<>();public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Set<Category> getCategories() {return categories;}public void setCategories(Set<Category> categories) {this.categories = categories;}}@Testpublic void testGet(){Category category = (Category) session.get(Category.class, 1);System.out.println(category.getName()); //需要连接中间表Set<Item> items = category.getItems();System.out.println(items.size()); }@Testpublic void testSave(){Category category1 = new Category();category1.setName("C-AA");Category category2 = new Category();category2.setName("C-BB");Item item1 = new Item();item1.setName("I-AA");Item item2 = new Item();item2.setName("I-BB");//设定关联关系 category1.getItems().add(item1);category1.getItems().add(item2);category2.getItems().add(item1);category2.getItems().add(item2);item1.getCategories().add(category1);item1.getCategories().add(category2);item2.getCategories().add(category1);item2.getCategories().add(category2);//执行保存操作 session.save(category1);session.save(category2);session.save(item1);session.save(item2);}
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="com.hibernate.n2n"><class name="Category" table="CATEGORIES"><id name="id" type="java.lang.Integer"><column name="ID" /><generator class="native" /></id><property name="name" type="java.lang.String"><column name="NAME" /></property><!-- table: 指定中间表 --><set name="items" table="CATEGORIES_ITEMS"><key><column name="C_ID" /></key><!-- 使用 many-to-many 指定多对多的关联关系. column 执行 Set 集合中的持久化类在中间表的外键列的名称 --><many-to-many class="Item" column="I_ID"></many-to-many></set></class> </hibernate-mapping>
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="com.hibernate.n2n"><class name="Item" table="ITEMS"><id name="id" type="java.lang.Integer"><column name="ID" /><generator class="native" /></id><property name="name" type="java.lang.String"><column name="NAME" /></property><set name="categories" table="CATEGORIES_ITEMS" inverse="true"><key column="I_ID"></key><many-to-many class="Category" column="C_ID"></many-to-many></set></class> </hibernate-mapping>
转载于:https://www.cnblogs.com/lusufei/p/7325535.html
Hibernate关联关系配置(一对多,一对一,多对多)相关推荐
- Hibernate关联关系配置(一对多、一对一和多对多)
第一种关联关系:一对多(多对一) "一对多"是最普遍的映射关系,简单来讲就如消费者与订单的关系. 一对多:从消费者角的度来说一个消费者可以有多个订单,即为一对多. 多对一:从订单的 ...
- (转)Hibernate关联映射——一对多(多对一)
http://blog.csdn.net/yerenyuan_pku/article/details/70152173 Hibernate关联映射--一对多(多对一) 我们以客户(Customer)与 ...
- 【数据表间关联关系】 一对多、多对一、一对一、多对多
关联映射:一对多/多对一 存在最普遍的映射关系,简单来讲就如球员与球队的关系: 一对多:从球队角度来说一个球队拥有多个球员 即为一对多 多对一:从球员角度来说多个球员属于一个球队 即为多对一 数据表间 ...
- (5)hibernate多对一,一对多,一对一,多对多
一 多对一关联 1 映射与原理分析 2 例子结构图 3代码 3.1 Department.java package com.learning;public class Department {priv ...
- hibernate中的一对多和多对多的映射关系
一多对需要注意的问题: 多看文字部分的内容,有助于理解 多 对多需要注意的问题: 转载于:https://www.cnblogs.com/wzhBlog/archive/2013/03/13/2958 ...
- Hibernate第四篇【集合映射、一对多和多对一】
前言 前面的我们使用的是一个表的操作,但我们实际的开发中不可能只使用一个表的-因此,本博文主要讲解关联映射 集合映射 需求分析:当用户购买商品,用户可能有多个地址. 数据库表 我们一般如下图一样设计数 ...
- mybatis高级映射(一对一,一对多,多对多)
http://www.cnblogs.com/selene/p/4627446.html 阿赫瓦里 生命对于某些人来说,一直都是美丽的,因为这些人的一生都在为某个梦想而奋斗!!! 博客园 首页 新随笔 ...
- Hibernate 中配置属性详解(hibernate.properties)
转自:https://blog.csdn.net/shudaqi2010/article/details/70324843 Hibernate能在各种不同环境下工作而设计的, 因此存在着大量的配置参数 ...
- Hibernate关联关系映射-----双向一对多/多对一映射配置
转自:http://blog.csdn.net/yifei12315/article/details/6985194 /// Hibernate: /// 双向关联就是有"一对多" ...
最新文章
- 工业4.0的十大关键词
- (012) java后台开发之Apache与Tomcat有什么关系和区别
- Oracle开发环境安装与使用
- Meteor资源国外优秀web APP 收藏
- android2.2 froyo竖屏显示
- python入门书?
- Mysql之1050错误解决办法
- Bat批处理脚本--常用命令
- qq音乐api android,QQ音乐
- linux 进入recovery 命令行,liunx-fastboot命令行的使用方法
- c语言中各个符号的意义及作用是什么,C语言各类符号意义以及用法是什么?
- word文档更新目录为什么更新不了?
- 初识strlen函数
- 理解“卷积” Understanding Convolutions
- hive注意事项01_空值处理
- ESP-IDF遇到的关于环境变量的问题
- Python pyautogui 实现自动发送消息
- SEO优化 - robots协议
- 2019,无数人改变命运的绝佳之年!(深度)
- 全加器在计算机的应用,两个半加器组成全加器的做法 浅谈全加器和半加器的应用...
热门文章
- iOS 中KVC、KVO、NSNotification、delegate 总结及区别
- FATAL ERROR: Could not find ./bin/my_print_defaults
- LAMP平台部署及应用
- 教你使用IOS内置的排错命令
- mysql with as_mysql数据库学习(第十六篇)- 视图
- Xamarin XAML语言教程构建进度条ProgressBar
- android phone驱动_[基础知识] 将 OneDrive 同步到 SD 卡等外部驱动器
- linux 安装gcc4.2,Linux操作系统下安装gcc4.2.*的方法
- python datetime计算时间差_Python中关于日期的计算总结
- 离开英伟达仅19个月,他交出了一块国产全功能GPU