Hibernate 映射关联关系
Hibernate关联关系注解配置简单理解

Hibernate关联关系注解配置简单理解Hibernate关联关系注解配置什么是关联关系?关联关系有哪⼏种?关联关系指实体之间的关系,也就是表与表之间的关系。
⼀个关系⽤两个属性来描述,数量性和⽅向性。
从数量上来看,表与表之间主要有三种关系,⼀对⼀,⼀对多,多对多。
加上关系的⽅向,还有⼀个多对⼀。
hibernate中关联关系的维护在实际的业务开发中,对于两个有关联的数据库实体,⽐如学⽣对教室,我们通常还需要在操作⼀⽅时,维护两⽅彼此之间的关系。
关系的维护分为两类:1.级联Cascade,在操作⼀⽅时,是否对另⼀⽅也执⾏同样的操作。
2.外键的维护inverse,在操作⼀⽅时,是否⾃动维护外键关系。
⽐如如果将多⽅的对象添加给以⼀的⼀⽅,因为外键由多⽅维护,hibernate 为了保证添加的这个多⽅对象的外键是正确的,会⾃动给这个多⽅的外键设置值(也就是⼀的⼀⽅的主键)外键维护,在xml配置中使⽤inverse属性,在注解中使⽤mappedBy注解来声明。
cascade与inverse1.cascade,指把对当前对象的操作级联到关联对象上。
⼀般在one to one ,one to many设置级联。
配置了这个属性后,当对当前对象执⾏如save等更新数据库的操作时,当前实体所关联的实体也会执⾏相应的操作。
2.inverse默认值为true, 表⽰让对⽅来维护关系。
设为false,⾃⼰维护关系。
inverse主要有两个作⽤:1)维护外键主控⽅保存时,是否⾃动update被控⽅的外键字段。
外键字段指向的就是当前保存的实体。
2)维护级联决定当前设置的级联是否有⽤,⾃⼰维护关系时,对⽅设置的级联就不会⽣效,对⽅保存时不会让本⽅也保存。
⽽对⽅维护关系,则与此相反。
@mappedBy注解1)mappedBy(name="对⽅标准代表当前实体的属性“)2)只存在于OneToOne,OneToMany,ManyToMany, 不能在ManyToOne中3)与joincolumn或jointable互斥。
hibernate核心,一对多,多对多映射讲解,看了就完全搞明白了

在many一方删除数据1
• 删除“五四大道”
inverse设为true,由many一方删除 从one一方去“删除”, Hibernate只是执行了 问题出在配置文件上 update语句。还是未删 没有配置set节点的inverse属性 除成功! 根本没有执行 Delete语句,数据 没有被删除!
– 配置Hibernate多对多关联,实现某OA系统项 目和人员对照关系的管理
本章目标
• 掌握单向many-to-one关联 • 掌握双向one-to-many关联 • 掌握many-to-many关联
实体间的关联
• 单向多对一
tblJd.getQx().getQxname();
• 单向一对多
TblJd jd = (TblJd)tblQx.getJds().get(0); jd.getJdname(); tblQx.getJds.add(jd);
小结
• 在租房系统中,房屋信息(Fwxx)与用户 (User)间也是多对一关系。如何配置映 射文件,使之可以通过下面的代码输出房 屋信息和发布该信息的用户名称? Fwxx fwxx = (Fwxx)super.get(Fwxx.class,1);
System.out.println( fwxx.getTitle() + "," + fwxx.getUser.getUname());
inverse是“反转”的意思,表示关联关系的控制权。 为true,表示由对方负责关联关系的添加和删除; 执行了delete语句, 为false,表示由自己负责维护关联关系。 删除成功
• 在many一方删除数据的正确做法:
Hibernate中关联关系映射策略研究与实现

业务逻辑层
l 接收表示层提交的表单数据, 进行相应的业务逻辑处理 l I处理通过持久层取得的原始数据,结果再送入持久层处理 I l 将业务逻辑层处理的结果反馈给表示层
业务逻辑层 持久层打交道
’
进一步提高软件开发 的效率以及 降低软件开发的难 度, 基于 We b的应 用 通 常 采用 四层 式 的软件 开发 框 架, 分层降低了系统各部分之间的耦合程度 , 增加了 系统 的可 维护 性和可 扩展 性L 。 2 ]
l 概
述
随着计算机软件开发技术 的快速发展 , b应 We 用程 序 的体 系结 构也 由单层 向两层 、 三层甚 至更 多层 次 的方 向发展 , e 用 程 序 通 常 涉 及 到 对 大 型 数 W b应 据库 的访 问操作 。两 层 的开 发模 型实 现 了应 用层 与 数 据 层 的分 离 , 应用 层 包括 用 户 界 面 、 务逻 辑 和数 业 据持久 化等 功 能 , 据层用 于保存 需要 进行 持久 化 的 数 数 据 。两层 模 型 中, 业务 逻 辑 、 据 持 久化 以及 用 将 数 户界 面都集 中在 应用 层 , 得 应 用 层 过 于臃 肿 , 使 因此 提 出了三层 的软 件开 发架构 。三 层架 构 中 , 应用 层划 分为 表示层 和业 务 逻 辑层 , 就 是 通 常所 说 的 MVC 这 ( dl Mo e—Vi e w—C n rl模 型 一视 图 一 控 制 ) 式 o to, 模 的系统 开发 架构 , MVC 模 式 的 广 泛 应 用 , 生 了 催 MVC框架 _ 。三层 模 型 虽 然 实 现 了业 务 逻 辑 和 用 1 ]
Hient brae的配 置 文 件 可 以使 用 hb raecg ient. f.
hibernate的n+1问题

什么叫n+1次select查询问题?在Session的缓存中存放的是相互关联的对象图。
默认情况下,当Hibernate 从数据库中加载Customer对象时,会同时加载所有关联的Order对象。
以Customer和Order类为例,假定ORDERS表的CUSTOMER_ID外键允许为null,图1列出了CUSTOMERS表和ORDERS表中的记录。
以下Session的find()方法用于到数据库中检索所有的Customer对象:List customerLists=session.find("from Customer as c");运行以上find()方法时,Hibernate将先查询CUSTOMERS表中所有的记录,然后根据每条记录的ID,到ORDERS表中查询有参照关系的记录,Hibernate将依次执行以下select语句:select * from CUSTOMERS;select * from ORDERS where CUSTOMER_ID=1;select * from ORDERS where CUSTOMER_ID=2;select * from ORDERS where CUSTOMER_ID=3;select * from ORDERS where CUSTOMER_ID=4;通过以上5条select语句,Hibernate最后加载了4个Customer对象和5个Order 对象,在内存中形成了一幅关联的对象图,参见图2。
Hibernate在检索与Customer关联的Order对象时,使用了默认的立即检索策略。
这种检索策略存在两大不足:(1) select语句的数目太多,需要频繁的访问数据库,会影响检索性能。
如果需要查询n个Customer对象,那么必须执行n+1次select查询语句。
这就是经典的n+1次select查询问题。
这种检索策略没有利用SQL的连接查询功能,例如以上5条select语句完全可以通过以下1条select语句来完成:select * from CUSTOMERS left outer join ORDERSon CUSTOMERS.ID=ORDERS.CUSTOMER_ID以上select语句使用了SQL的左外连接查询功能,能够在一条select语句中查询出CUSTOMERS表的所有记录,以及匹配的ORDERS表的记录。
hibernate最精细总结 java

Hibernate总结注:重点讲解关联映射总结人:张焕邮箱:zhang343489603@欢迎交流讨论。
目录1)核心接口简介2)Hibernate版本更新情况3)Hibernate关联映射4)简单属性查询5)Hibernate与延迟加载6)hibernate 中Criteria 的使用介绍7) Hibernate程序性能优化Hibernate优点:1、封装了jdbc,简化了很多重复性代码。
2、简化了DAO层编码工作,使开发更对象化了。
3、移植性好,支持各种数据库,如果换个数据库只要在配置文件中变换配置就可以了,不用改变hibernate代码。
4、支持透明持久化,因为hibernate操作的是纯粹的(pojo)java类,没有实现任何接口,没有侵入性。
所以说它是一个轻量级框架。
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。
Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web 应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。
1)核心接口简介:Hibernate的核心接口一共有6个,分别为:Session、SessionFactory、Transaction、Query、Criteria和Configuration。
这6个核心接口在任何开发中都会用到。
通过这些接口,不仅可以对持久化对象进行存取,还能够进行事务控制。
下面对这6个核心接口分别加以介绍。
Session接口Session接口负责执行被持久化对象的CRUD操作(CRUD的任务是完成与数据库的交流,包含了很多常见的SQL语句。
)。
但需要注意的是Session对象是非线程安全的。
同时,Hibernate的session不同于JSP应用中的HttpSession。
13-Hibernate关联关系映射:一对多孤儿删除

13-Hibernate关联关系映射:⼀对多孤⼉删除persist和merge是JPA提供的内容none是不使⽤级联,save-update是保存和更新的时候级联hibernate级联的取值none:不使⽤级联save-update:保存和更新时级联delete:删除的时候级联all:delete-orphan:孤⼉删除,孤⼦删除*仅限于⼀对多,只有⼀对多的时候才有类似⽗⼦关系的存在,才有⽗⼦表的存在。
认为⼀的⼀⽅是⽗⽅。
因为⼀个⽗亲是可以有多个孩⼦的。
多的⼀⽅是⼦的⼀⽅。
*当⼀个客户与某个订单解除关系,其实就是将外键置为null,如果你的订单没有所属的客户,那你的订单还有意义吗?订单没有了所属客户,就相当于⼀个孩⼦没有了⽗亲,将这种记录就删除了,这就叫做孤⼉删除。
*但是这只有在⼀对多的情况下才存在。
多对多的情况哪有这种关系,多对多就是多个⽗亲多个⼉⼦,这就不合理了。
⼀的⼀⽅是⽗⽅,多的⼀⽅是⼦⽅。
All-delete-orphan:我们现在想让1号客户和1号订单解除关系:⼀个部门可以有多个员⼯,⼀个员⼯只能属于⼀个部门。
解除关系就是把外键置为空了,就是把外键置为null了。
Hibernate:selectcustomer0_.cid as cid0_0_,customer0_.cname as cname0_0_fromcustomer customer0_wherecustomer0_.cid=?Hibernate:selectorder0_.oid as oid1_0_,order0_.addr as addr1_0_,order0_.cno as cno1_0_fromorders order0_whereorder0_.oid=?Hibernate:selectorders0_.cno as cno0_1_,orders0_.oid as oid1_,orders0_.oid as oid1_0_,orders0_.addr as addr1_0_,orders0_.cno as cno1_0_fromorders orders0_whereorders0_.cno=?Hibernate:updateorderssetcno=nullwherecno=?这个时候我们再看客户和订单都还在。
关系映射

T_person --------------------------------------Id name --------------------------------------1 张三 2 李四 T_idCard --------------------------------------Id cardNo --------------------------------------1 1234567890 2 2345678901
One2One fk1
<class name="com.sinoest.hibernate.IdCard" table="t_idCard"> <id name="id"> <generator class="native"/> </id> <property name="cardNo"/> </class>
many2one
public class User { private int id; private String name; private String name; private Group group; public int getId() { return id; } …. } } public int getId() { return id; } public void setId(int id) { this.id = id; } …. Public class Group{ prlass Classes { private int id; private String name; private Set students; public int getId() { return id; } public void setId(int id) { this.id = id; } ……. public class Student { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; }
第5章 Hibernate持久层技术(1)

- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Hibernate 映射关联关系一、映射多对一关联关系。
1.单向的多对一(1)以Customer 和Order 为例:一个用户可以发出多个订单,而一个订单只能属于一个客户。
从Order 到Customer 是多对一关联关系。
(2)创建Customer 和Order 表。
Create(3)用Intellij Idea 自动生成关联关系,以及对应的Entitiy.hbm.xml 和持久化类。
说明:其中Type 是用来修饰对应的Attribute Name 的。
在Order 端,定义Customer 类,一个订单属于一个客户。
而在Customer 端,一个客户可以有多个订单,因为是单向的,所以这里放弃属性的添加。
在Join Columns 定义了Order 和Customer 之间的关联关系,order 表中的customer_id 外键和customer 表中的customer_id 主键关联。
来看生成的Schema:没有勾选customer_id,是因为Intellij Idea 没法直接映射为Customer 类型的customer。
Order.hbm.xml使用<many-to-one> 节点来维护多对一关联关系。
name 属性:多这一端关联的一那一端的属性的名称。
class 属性:关联的一端的属性的类型。
column 属性:一那一端在多的一端对应的数据表中的外键。
可以任意命名,但需要和数据表中的字段对应。
(4)单向多对一的CRUD 以及需要注意的问题。
<1> 新增①先保存一的一端Customer,后保存多的一端Order。
Save.java打印SQL:Output结论:发送了3条INSERT 语句。
②先保存多的一端Order,再保存一的一端Customer。
Save2.java打印SQL:Output2结论:发送了3条INSERT 语句,2条UPDATE 语句。
总结:在单向多对一的关联关系下,先插入 1 的一端会减少SQL 语句的执行,性能更高。
<2>删除先删除1的一端。
Delete.java控制台打印:Cannot delete or update a parent row: a foreign key constraint fails (`hibernate`.`order`, CONSTRAINT `FK_m6q2ofkj1g5aobtb2p00ajpqg` FOREIGN KEY (`customer_id`) REFERENCES `customer` (`customer_id`))结论:在不设置级联关系的前提下,不能删除 1 的一端。
<3>更新Update.javaOutput<4>查询①查询n 的一端,但是不使用查询出来关联的 1 的一端的对象。
@Testpublic void testMany2OneGet() {Order order = (Order) session.get(Order.class, 1);System.out.println(order.getCustomer().getClass().getName());}复制代码Hibernate:selectorder0_.order_id as order_id1_1_0_,order0_.order_name as order_na2_1_0_,order0_.customer_id as customer3_1_0_fromhibernate.order order0_whereorder0_.order_id=?order1com.nucsoft.hibernate.Customer_$$_jvst30c_1复制代码②查询n 的一端,使用查询出来关联的 1 的一端的对象。
@Testpublic void testMany2OneGet() {Order order = (Order) session.get(Order.class, 1);System.out.println(order.getCustomer().getClass().getName());order.getCustomer().getCustomerName();}复制代码Hibernate:selectorder0_.order_id as order_id1_1_0_,order0_.order_name as order_na2_1_0_,order0_.customer_id as customer3_1_0_fromhibernate.order order0_whereorder0_.order_id=?com.nucsoft.hibernate.Customer_$$_jvst30c_1Hibernate:selectcustomer0_.customer_id as customer1_0_0_,customer0_.customer_name as customer2_0_0_fromhibernate.customer customer0_wherecustomer0_.customer_id=?复制代码总结:可以发现,采用的是懒加载机制,即获取到的 1 的一端的对象是一个代理对象。
只有在使用这个对象的属性的情况下,才会发送SQL 语句。
③由懒加载机制引发的懒加载异常。
复制代码@Testpublic void testMany2OneGet() {Order order = (Order) session.get(Order.class, 1);System.out.println(order.getCustomer().getClass().getName());session.close();order.getCustomer().getCustomerName();}复制代码zyInitializationException: could not initialize proxy - no Session在需要使用对象之前,关闭了Session 连接,由此会引发LazyInitializationException 异常。
2.双向的多对一(1)还是以Order 和Customer 为例:双向的多对一不仅仅要在Order 类中定义一个Customer 属性,而在Customer 类中也需定义存放Order 对象的集合属性。
(2)创建Order 和Customer 表和创建单向多对一相同。
(3)通过Intellij Idea 生成简单的持久化类和Entity.hbm.xml 文件。
手动的去建立关联关系。
<1>生成简单的持久化类和Entity.hbm.xml 文件Customer.javaOrder.javaCustomer.hbm.xmlOrder.hbm.xml<2>手动建立关联关系①在Order 一端建立多对一的关联关系。
在Order 持久化类中添加Customer 类型的一个属性customer。
在Order.hbm.xml 文件中添加多对一的关联关系。
同时修改主键生成方式为native。
②在Customer 一端建立一对多的关联关系。
在Customer 持久化类中添加Order 的一个集合orders。
在Customer.hbm.xml 添加一对多的关联关系。
同时修改主键生成方式为native。
③详细说明:在Customer.hbm.xml 文件中添加一对多的关联关系。
当Session 从数据库中加载Java 集合时,创建的是Hibernate 内置的集合类的实例。
因此在持久化类中定义集合属性时需要定义成接口类型,不能是具体的某个实现类。
Hibernate 内置的集合具有集合代理功能,因为有代理功能,所以支持延迟检索策略。
在定义集合的时候,通常将其初始化为集合实现类的一个实例,防止NullPointerException。
Hibernate 使用<set> 元素来映射Set 类型的属性。
1 的一端的Set 类型属性数据还是存放在n 的一端。
④set 元素name 属性:待映射的Set 类型的属性的属性名称。
table 属性:待映射的Set 属性的泛型类型所对应的表。
key 子元素:column 属性,多的一端的外键名称。
one-to-many 子元素:class 属性,n 的一端的持久化类名称。
对应关系如图。
⑤最终的实体类和Entity.hbm.xml 文件。
Customer.javaOrder.javaCustomer.hbm.xmlOrder.hbm.xml(4)通过Intellij Idea 直接生成双向的多对一的关联关系。
<1>为生成的每个Entity.hbm.xml 文件添加主键生成方式。
<2>为Customer 类中的orders 属性进行初始化。
<3>最终的持久化类和Entity.hbm.xml。
Customer.javaOrder.javaCustomer.hbm.xmlOrder.hbm.xml<4>对比发现,通过Intellij Idea 自动生成的Customer.hbm.xml 文件中set 元素多了一个inverse 属性。
稍后进行说明。
(5)双向多对一的CRUD 和需要注意的问题<1>新增①双方都维护关联关系,即没有设置inverse 属性,且没有添加非空约束。
先保存 1 的一端,再保存n 的一端。
Save.java打印SQL:Output结果:打印了 3 条INSERT 语句,2 条UPDATE 语句先保存n 的一端,再保存 1 的一端。
Save2.java打印SQL :Output2结果:打印了 3 条INSERT 语句,4 条UPDATE 语句。
原因,双方都维护这关联关系。
②双方都维护关联关系,即没有设置inverse 属性,对order 表中的customer_id 列添加非空约束(需要更改两个地方)。
先保存n 的一端,再保存 1 的一端,会抛出异常。
org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation : com.nucsoft.hibernate.Order.customer -> com.nucsoft.hibernate.Customer③ 1 的一端放弃维护关联关系,只由n 的一端来维护。