Hibernate 映射关联关系

合集下载

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核心,一对多,多对多映射讲解,看了就完全搞明白了

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中关联关系映射策略研究与实现

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问题

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最精细总结 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关联关系映射:一对多孤儿删除

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=?这个时候我们再看客户和订单都还在。

关系映射

关系映射
单向关联Person----->IdCard
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)

第5章 Hibernate持久层技术(1)
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!--数据库链接参数--> <property name="connection.url">jdbc:mysql://localhost:3306/mydb</property> <property name="ername">root</property> <property name="connection.password">admin</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <!-- 方言 --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!--映射文件--> <mapping resource="com/entity/Customer.hbm.xml" /> </session-factory> </hibernate-configuration>

Hibernate_映射配置文件详解

Hibernate_映射配置文件详解
–hibernate.properties –hibernate.cfg.xml
Prepared by TongGang
hibernate.cfg.xml的常用属性
• • • • • • • • • connection.url:数据库URL ername:数据库用户名 connection.password:数据库用户密码 connection.driver_class:数据库JDBC驱动 show_sql:是否将运行期生成的SQL输出到日志以供调试。取 show_sql 值 true | false dialect:配置数据库的方言,根据底层的数据库不同产生不 dialect 同的sql语句,Hibernate 会针对数据库的特性在访问时进行 优化。 hbm2ddl.auto:在启动和停止时自动地创建,更新或删除数据 hbm2ddl.auto 库模式。取值 create | update | create-drop resource:映射文件配置,配置文件名必须包含其相 mapping resource 对于根的全路径 connection.datasource :JNDI数据源的名称
• Class:定义一个持久化类 Class: • name (可选): 持久化类(或者接 (可选): 持久化类( 可选 口)的类名 • table (可选 - 默认是类的非全限 (可选 定名): 定名): 对应的数据库表名 • discriminator-value (可选 - 默 discriminator(可选 认和类名一样): 认和类名一样): 一个用于区分不 同的子类的值,在多态行为时使用。 同的子类的值,在多态行为时使用。 它可以接受的值包括 null 和 not null。 null。
Prepared by TongGang

Hibernate注释大全

Hibernate注释大全
inverseJoinColumns = @JoinColumn( name="monkey_id")
)
public Set<Monkey> getTrainedMonkeys() {
...
}
@Entity
public class Monkey {
... //no bidir
用 cascading 实现传播持久化(Transitive persistence)
cascade 属性接受值为 CascadeType 数组,其类型如下:
? CascadeType.PERSIST: cascades the persist (create) operation to associated entities persist() is called or if the entity is managed 如果一个实体是受管状态,或者当 persist() 函数被调用时,触发级联创建(create)操作。
@SecondaryTable(name="Cat2", uniqueConstraints={
@UniqueConstraint(columnNames={"storyPart2"})})
})
public class Cat implements Serializable {
...
}
public class MyDao {
doStuff() {
Query q = s.getNamedQuery("night.moreRecentThan");
q.setDate( "date", aMonthAgo );

Hibernate基础知识详解

Hibernate基础知识详解

Hibernate基础知识详解<hibernate-mapping><class name="*.*.*" table="t_customer" catalog="***"><id name="id" column="c_id"><generator class="identity"/></id><property name="name" column="c_name" length="20"/><set name="orders" inverse="false" cascade="save-update"><key column="c_customer_id"/></set></class></hibernate-mapping>(1)统⼀声明包名,这样在<class>中就不需要写类的全名。

(2)关于<class>标签配置name 属性:类的全名称table 表的名称,可以省略,这时表的名称就与类名⼀致catalog 属性:数据库名称可以省略.如果省略,参考核⼼配置⽂件中 url 路径中的库名称(3)关于<id>标签,<id>是⽤于建⽴类中的属性与表中的主键映射。

name 类中的属性名称column 表中的主键名称 column 它也可以省略,这时列名就与类中属性名称⼀致length 字段长度type 属性指定类型<generator>它主要是描述主键⽣成策略。

Hibernate(V)——一对多与多对多关联关系映射(xml与注解)总结

Hibernate(V)——一对多与多对多关联关系映射(xml与注解)总结

Hibernate(V)——一对多与多对多关联关系映射(xml与注解)总结引言简要介绍Hibernate框架以及关联关系映射在数据库设计中的重要性。

Hibernate关联关系映射概述关联关系的重要性讨论在现实世界中对象间关系的重要性以及如何在数据库中表示这些关系。

Hibernate关联关系类型列举Hibernate支持的关联关系类型,包括一对一、一对多、多对一和多对多。

一对多关联关系映射概念解释解释一对多关联关系的概念,例如一个部门拥有多个员工。

XML映射方式详细描述如何在XML映射文件中配置一对多关联关系。

实体类定义展示一对多关系中实体类的Java代码示例。

XML映射文件提供一对多关系映射的XML配置示例。

注解映射方式详细描述如何使用注解配置一对多关联关系。

实体类定义展示使用注解的一对多关系中实体类的Java代码示例。

注解配置提供一对多关系映射的注解配置示例。

多对多关联关系映射概念解释解释多对多关联关系的概念,例如学生和课程之间的关联。

XML映射方式详细描述如何在XML映射文件中配置多对多关联关系。

实体类定义展示多对多关系中实体类的Java代码示例。

XML映射文件提供多对多关系映射的XML配置示例。

注解映射方式详细描述如何使用注解配置多对多关联关系。

实体类定义展示使用注解的多对多关系中实体类的Java代码示例。

注解配置提供多对多关系映射的注解配置示例。

关联关系映射的高级特性级联操作讨论级联保存、更新和删除的概念及其配置。

双向关系管理解释如何管理双向关联关系,确保数据的一致性。

延迟加载与即时加载讨论延迟加载和即时加载的概念及其在关联关系中的应用。

实践案例分析一对多关联关系案例通过一个具体的一对多关联关系案例,展示映射配置和数据操作。

多对多关联关系案例通过一个具体的多对多关联关系案例,展示映射配置和数据操作。

常见问题与解决方案一对多关联关系常见问题列举一对多关联关系映射中可能遇到的问题及其解决方案。

Hibernate框架简介

Hibernate框架简介

Hibernate框架简介⼀、什么是 Hibernate?Hibernate 是⼀个基于元数据的轻量级的 ORM 框架:1、元数据(Meta Data):data about data(数据的数据),也就是说描述⼀个对象数据,相当于这个对象的上下⽂环境。

2、轻量级:占⽤资源少,没有侵⼊性。

(其实我认为这只是相对⽽⾔,如果和 Ibatis 相⽐,它到成重量级的了)。

3、ORM:(Object Relation Mapping)对象关系数据库的映射这是 Hibernate 框架的重点,也就是说将我们程序中的实体(bean,这⾥也叫 POJO)和数据库中的表进⾏映射。

java 类型和 sql类型映射,⾯向对象设计和关系型数据库设计的映射,从⽽我们只需要将更多的精⼒放到业务中,⽽不是 sql 数据库⽅⾯。

4、POJO:(Plain Ordinary Java Object),⽆格式的普通 java 对象,也就是上边说的实体,和数据库做映射的简单类。

只是在这⾥提出了⼀个新的名词⽽已。

总⽽⾔之,Hibernate 就是将我们的数据库表和程序的 POJO 类进⾏映射,数据的操作进⾏了封装,使我们不⽤把数据库弄得⾮常精通,我们会⾯向对象编程就可以了,这样⼤⼤提⾼了我们的编程效率,⽽且对个⼈的知识要求也降低了。

⼆、Hibernate 基础 ----- 数据库操作在 Hibernate 出现之前,对数据库操作是基于 JDBC,这中间经历了操作 JDBC、封装 JDBC、ORM 三个阶段。

1、操作 JDBC 阶段:本阶段即在调⽤ JDBC 连接数据库的包时,需要⾃⼰进⾏编写的进⾏数据库⽤户登录验证的那段代码。

在这段代码中可以执⾏ SQL 语句进⾏数据查询、插⼊、删除等。

2、封装 JDBC 阶段:由于仅仅只是操作 JDBC,使得在实现不同逻辑功能时,都要重新编写进⾏数据库⽤户登陆验证的那段代码,使得代码重复很严重。

为此,引⼊了 JavaBean的技术,书写⼀个 DBAccess.java 类进⾏数据库⽤户登陆验证和数据库操作,并把其中进⾏数据库操作部分封装成不同的函数,那么实现后续的逻辑功能时只需调⽤这些函数即可实现。

one-to-one

one-to-one
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"/hibernate-mapping-3.0.dtd">
</class>
</hibernate-mapping>
Room.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hiber">
<class name="Room" table="room">
<id name="id" column="room_id" unsaved-value="0">
<generator class="increment"></generator>
</id>
<property name="name" column="name" type="string"></property>

hibernate 关联查询原理

hibernate 关联查询原理

hibernate 关联查询原理
Hibernate 是一个流行的ORM(对象关系映射)框架,它提供了一种方便的方式来进行数据库操作,包括关联查询。

关联查询是指通过在一个查询中涉及多个表之间的关联关系来获取相关联的数据。

在Hibernate 中,关联查询的原理基于以下几个关键概念和技术:
1. 对象关系映射(ORM):Hibernate 负责将数据库表映射到Java 对象。

在关联查询中,Hibernate 会根据映射配置文件中的关联关系,将相关联的对象之间建立连接。

2. 延迟加载:Hibernate 支持延迟加载的策略,这意味着在关联查询时,只有在需要时才会实际从数据库中加载关联的数据。

这样可以避免不必要的数据加载和性能消耗。

3. 外键和关联映射:在映射配置文件中,你可以定义对象之间的关联关系,包括外键和映射的字段。

Hibernate 利用这些信息在查询时建立对象之间的连接。

4. SQL 查询语句生成:Hibernate 根据你在Java 代码中编写的查询条件和关联关系,自动生成对应的SQL 查询语句。

它会将对象
之间的关联关系转换为适当的JOIN 操作。

5. 结果集映射:在关联查询执行后,Hibernate 将返回的数据库结果集映射回相关的Java 对象。

它根据映射配置文件中的规则,将每行数据映射到相应的对象属性上,并维护对象之间的关联关系。

6. 缓存和一级缓存:Hibernate 使用缓存来提高查询性能。

在关联查询中,它会利用一级缓存来存储已经加载的对象,避免重复从数据库中获取。

Hibernate框架ORM常见数据关联分析

Hibernate框架ORM常见数据关联分析
统中常见的一种关联关系。多对多数据关联可 以看做是
2 . 多方对象插入 。( 1 ) 子表对应 的h b m映射文件 中的
外键字段 “ n o t . n u l l ”属性为f a l s e t  ̄ - , j " 。多方 对象中 的一 方对象属性为空时 ,子表正常插入 ,且 只插入子表 ;多 方对象中的一方对象 为瞬态时 ,会报 “ n o t . n u l l p r o p e t r y
A C A DE MI C R E S E A R C H 学术 研 究
H i b e r n a t e 框架O R M常见数据关联分析
◆ 郭 朗
摘 要 :本 文 深入探 讨 了Hi b e r n a t e 轻 量 级 oRM框 架 的数 据 关联 原 理 ,对 该 框 架
在一对多数据关联 中出现的各种 问题进行 了分析 ,并提 出了解 决方案 。
键 ;多方对象中的一方对象态为持久态时 ,能插入多方 对象到子表 :A可以通过先插入一个父表对象或者查询 父表得到一个一方的持久化对象 。B以上成功级联插入
的情 况 均 是 在 c a s c a d e =“ t r u e ” 属 性 下 完 成 的 ,如 果 该
时 ,此时表示s E T 集合中有子表的对象。插人隋况如下 :
①当子表对应的h b m映射文件 中的外键字段n o t . n u l l
属性设置为 t r u e ,此时如果一方S E T 集合 中的多方对象 的外键为空 ,插入会 出 “ n o t . n u l l p r o p e r t y r e f e r e n c e s a
n u l l o r t r a n s i e n t v a l u e :错误” ,此错误为H i b e r n a t e 检查

hibernate笔记

hibernate笔记

configuration.addClass(Customer.class);sf = configuration.buildSessionFactory();}(2)新增保存:save方法/**保存*/@Testpublic void save(){Session s = sf.openSession();Transaction tr = s.beginTransaction();Customer c = new Customer();c.setName("洪七公");c.setAge(60);c.setDes("帮助");s.save(c);mit();//实质上执行了2步操作,1:s.flush();//清理缓存,让session缓存中的数据与数据库同步,2:事务提交s.close();//Session的缓存就没有了}(3)更新:update方法/**更新*/@Testpublic void update(){Session s = sf.openSession();Transaction tr = s.beginTransaction();Customer c = new Customer();c.setId(3);c.setName("黄老邪");c.setAge(59);c.setDes("药师");s.update(c);mit();s.close();}(4)删除:delete方法@Testpublic void delete(){Session s = sf.openSession();Transaction tr = s.beginTransaction();Customer c = new Customer();c.setId(3);s.delete(c);mit();s.close();}(5)查询:get和load方法/**使用ID查询信息*/@Testpublic void findCustomerById(){Session s = sf.openSession();Transaction tr = s.beginTransaction();Customer c = (Customer) s.get(Customer.class, 2);System.out.println(c.getId()+" "+c.getName()+""+c.getAge()+" "+c.getDes());mit();s.close();}(6)查询:query查询(支持hql语句,sql语句,qbc语句)/**查询所有信息*/@Testpublic void findAllCustomerList(){Session s = sf.openSession();Transaction tr = s.beginTransaction();/**使用Hql语句:操作持久对象和属性* 复习sql语句:操作数据库表和数据库表的列*/Query query = s.createQuery("from Customer o");List<Customer> list = query.list();if(list!=null && list.size()>0){for(Customer c:list){System.out.println(c.getId()+" "+c.getName()+" "+c.getAge()+" "+c.getDes());}}mit();s.close();}●hibernate在内存地址中存在一个一级缓存,存在在一级缓存中的对象,就说明该对象具有了持久化的能力,如果对象具有持久化能力就能操作数据库。

《Web系统开发课程设计》

《Web系统开发课程设计》

信息科学与技术学院《Web系统开发课程设计》实训报告书题目:Web系统开发课程设计专业:信息管理与信息系统班级:姓名:学号:指导老师:设计时间:2017年5月15日~2017年5月19日第一天一、学习内容1)软件安装(myEclipse10.0、mysql 5.1+navicat、Tomcat7.0)2)Hibernate 的基本配置和核心文件、关系映射文件回顾3)单表操作和多对多的操作4)Hibernate级联查询(自连接左外连接右外连接)二、学习代码er.javapackage com.itedu.entity;public class User {private Integer id;private String username;private String password;private String alias;//描述public User(Integer id, String username, String password, String alias) { super();this.id = id;ername = username;this.password = password;this.alias = alias;}public User() {super();}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {ername = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getAlias() {return alias;}public void setAlias(String alias) {this.alias = alias;}public String toString() {return"User [id=" + id + ", username=" + username + ", password="+ password + ", alias=" + alias + "]";}}er.hbm.xml<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping><class name="er" table="t_user"><id name="id"column="id"><!-- 主键生成策略 --><generator class="native"></generator></id><property name="username"column="username"></property><property name="password"column="password"></property><property name="alias"column="alias"></property> </class></hibernate-mapping>3.HibernateTest.javapackage com.itedu.hibernatetest;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.cfg.Configuration;import org.junit.Test;import er;public class HibernateTest {public void test(){//1.加载ConfigurationConfiguration cf = new Configuration();cf.configure();//2.先拿到sessionFactorySessionFactory sf = cf.buildSessionFactory();//3.seesion CRUD操作Session session = sf.openSession();Transaction tx = session.beginTransaction();//4.开启事务User user = new User();user.setId(1);user.setUsername("张三");user.setPassword("123");user.setAlias("你好!");session.save(user);//5.提交事务mit();session.close();sf.close();}}4.Hibernate.cfg.xml<?xml version="1.0"?><!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration><session-factory><!-- 配置数据库信息 --><!--1. 配置数据库 --><property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</p roperty><property name="hibernate.connection.url">jdbc:mysql:///java0515</property><property name="ername">root</property><property name="hibernate.connection.password">123456</property><property name="hibernate.show_sql">true</property><property name="hibernate.format_sql">true</property><propertyname="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property><property name="hibernate.hbm2ddl.auto">update</property>5.Customer.javapackage com.itedu.entity;import java.util.HashSet;import java.util.Set;public class Customer {private Integer cid;private String custName;private String custLevel;private String custSource;private String custPhone;private String custMobile;private Set<LinkedPerson> linkedset = new HashSet<LinkedPerson>(); public Set<LinkedPerson> getLinkedset() {return linkedset;}public void setLinkedset(Set<LinkedPerson> linkedset) {this.linkedset = linkedset;}public Integer getCid() {return cid;}public void setCid(Integer cid) {this.cid = cid;}public String getCustName() {return custName;}public void setCustName(String custName) {this.custName = custName;}public String getCustLevel() {return custLevel;}public void setCustLevel(String custLevel) {this.custLevel = custLevel;}public String getCustSource() {return custSource;}public void setCustSource(String custSource) {this.custSource = custSource;}public String getCustPhone() {return custPhone;}public void setCustPhone(String custPhone) {this.custPhone = custPhone;}public String getCustMobile() {return custMobile;}public void setCustMobile(String custMobile) {this.custMobile = custMobile;}public String toString() {return "Customer [cid=" + cid + ", custName=" + custName+ ", custLevel=" + custLevel + ", custSource=" + custSource+ ", custPhone=" + custPhone + ", custMobile=" + custMobile+ "]";}}6.customer.hbm.xml<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.itedu.entity.Customer"table="t_customer"><id name="cid"column="cid"><generator class="native"></generator></id><property name="custName"column="custName"></property><property name="custLevel"column="custLevel"></property><property name="custSource"column="custSource"></property><property name="custPhone"column="custPhone"></property><property name="custMobile"column="custMobile"></property><set name="linkedset"cascade="save-update,delete"batch-size="10"> <key column="clid"></key><one-to-many class="com.itedu.entity.LinkedPerson"></one-to-many> </set></class></hibernate-mapping>7.LinkedPerson.javapackage com.itedu.entity;public class LinkedPerson {private Integer lkp_id;//联系人编号(主键)private String lkp_name;//联系人姓名private String lkp_gender;//联系人性别private String lkp_phone;//联系人办公电话//声明多的这个表的实体类对象private Customer customer;public Customer getCustomer() {return customer;}public void setCustomer(Customer customer) {this.customer = customer;}public Integer getLkp_id() {return lkp_id;}public void setLkp_id(Integer lkp_id) {this.lkp_id = lkp_id;}public String getLkp_name() {return lkp_name;}public void setLkp_name(String lkp_name) {this.lkp_name = lkp_name;}public String getLkp_gender() {return lkp_gender;}public void setLkp_gender(String lkp_gender) {this.lkp_gender = lkp_gender;}public String getLkp_phone() {return lkp_phone;}public void setLkp_phone(String lkp_phone) {this.lkp_phone = lkp_phone;}}8.LinkedPerson.hbm.xml<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.itedu.entity.LinkedPerson"table="t_linkperson"><id name="lkp_id"column="lkp_id"><!-- 主键的生成策略 native 代表这个节点是主键--><generator class="native"></generator></id><property name="lkp_name"column="lkp_name"></property><property name="lkp_gender"column="lkp_gender"></property><property name="lkp_phone"column="lkp_phone"></property><many-to-one name="customer"class="com.itedu.entity.Customer" column="clid"></many-to-one></class></hibernate-mapping>9.Hibernate.cfg.xml<?xml version="1.0"?><!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration><session-factory><propertyname="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <propertyname="hibernate.connection.url">jdbc:mysql:///java0515</property><property name="ername">root</property><property name="hibernate.connection.password">123456</property> <!-- 可以显示输出sql语句的配置信息 --><property name="hibernate.show_sql">true</property><!-- 格式化sql语句 --><property name="hibernate.format_sql">true</property><!-- 叫做hibernate的方言比如:hibernate要支持多个不同的数据库,而且还要支持不同sql语句查询分页(limit),排序(order) --><propertyname="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property><!-- 如果有t_user这张表,那么就更新,如果说没有表,则创建 --> <property name="hibernate.hbm2ddl.auto">update</property><!-- 关联对象映射文件 --><mapping resource="com/itedu/entity/Customer.hbm.xml"></mapping><mapping resource="com/itedu/entity/LinkedPerson.hbm.xml"></mapping> </session-factory></hibernate-configuration>三、学习心得(问题解决)1)Hibernate简化了JDBC 繁琐的编码, 它通过映射来实现java对象和数据库的联系。

hibernate多表关联查询

hibernate多表关联查询

Hibernate是典型的OPM工具,它将每一个物理表格(Table)映射成为对象(Object),这发挥了面向对象的优势,使设计和开发人员可以从面向对象的角度来进行对数据库的管理。

在设计到多表操作时,Hibernate提供了与数据库表关系相对应的对象映射关系,一对一、一对多和多对多在这里都可以通过Hibernate的对象映射关系(Set等)来实现。

这为一般情况下的数据库多表操作提供了便捷途径。

关于这方面的介绍已经很多,在这里不再复述。

但是,在有些情况下的多表操作,比如一个统计顾客在2005年的消费总金额的SQL操作如下:select , count(a.fee) mix(a.chargeBeginTime) max(a.chargeEndTime) from charge a, customer b where a.idCustomer = b.idCustomer and a.chargeBeginTime >='2005-01-01' and a.chargeEndTime < '2005-12-31' gourp by a.idCustomercustomer表和charge结构如下:customer表结构:+------------+-------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+------------+-------------+------+-----+---------+-------+| IdCustomer | varchar(32) | | PRI | | || Name | varchar(30) | | | | |+------------+-------------+------+-----+---------+-------+charge表结构:+-----------------+-------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+-----------------+-------------+------+-----+---------+-------+| IdCharge | varchar(32) | | PRI | | || Fee | double | YES | | NULL | || ChargeTimeBegin | datetime | YES | | NULL | || ChargeTimeEnd | datetime | YES | | NULL | |+-----------------+-------------+------+-----+---------+-------+在Hibernate的自带文档中有类似下面的多表查询操作提示:“select new OjbectC(field1, field2,...) from ObjectA a, ObjectB b ...”,分析一下可以看出这个操作有两个缺点:1)必须声明并创建类ObjectC,根据Hibernate的特点,需要写一个ObjectC.hbm.XML 的PO映射,在只用到创建查询结果的新对象的时候,这个映射可以是个虚的,即可以没有一个真正的数据库表和ObjectC对应,但是这样的一个虚设的逻辑显然已经违背了Hibernate的思想初衷;2)这个办法只能查询出但条结果记录并只能创建单个的ObjectC对象,这是很局限的,因此在某些情况下根本不能使用(比如本例)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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 的一端来维护。

相关文档
最新文档