hibernate关联对象的增删改查------查
本篇博客是之前博客hibernate关联对象的增删改查------查 的后继,本篇代码的设定都在前文已经写好,因此读这篇之前,请先移步上一篇博客
//代码片5
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Dream d=new Dream();
d.setDescription("marry glt");
Person p=new Person();
p.setName("dlf");
d.setPerson(p);
session.save(d);
session.save(p);
session.getTransaction().commit();
session = sessionFactory.getCurrentSession();
session.beginTransaction();
Dream dream=(Dream) session.get(Dream.class, 1);
System.out.println(dream.getPerson().getName()+" ddddd");
session.getTransaction().commit();
对应代码5而言,get dream的时候发的sql语句为
select
dream0_.id as id0_1_,
dream0_.description as descript2_0_1_,
dream0_.personId as personId0_1_,
person1_.id as id1_0_,
person1_.myname as myname1_0_
from
Dream dream0_
left outer join
Person person1_
on dream0_.personId=person1_.id
where
dream0_.id=?
换言之,get dream的时候,我们也获得了对应的person。
有3个问题
1 执行代码5的时候,dream的manytoone的cascade已经去掉了。
2 如果把Dream dream=(Dream) session.get(Dream.class, 1);与之前保存对象的语句放到一个session里,发的sql语句竟然是update。但是,System.out.println(dream.getPerson().getName()+" ddddd");依然能输入person的name。
我们能得出规律
在多对一,一对多的情况下,当我们读取多的一方时,默认也会读取一的一方。(这个规律与cascade无关)
反过来,如果我读一的一方呢,会不会也自动读出多的一方呢?
我们看代码
//代码6
public void testGetPerson() {
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
Person p = (Person)s.get(Person.class, 2);
s.getTransaction().commit();
}
这个时候它发的sql语句是:
select
person0_.id as id1_0_,
person0_.myname as myname1_0_
from
Person person0_
where
person0_.id=?
并没有去主动获得person对应的dream。
那如果我想获得dream呢?
hibernate的管理关系中还有一个参数叫fetch。它管的就是在读取某个对象时,是否需要读取与之相关的另一个对象。
通过查阅api文档,我们知道fetch的取值是fetchtype型的。而fetchtype是个Enum类型的。
可以取值LAZY与EAGER。
这个两个值是什么意思?
猜一猜,我们大概都是知道,eager就是主动获取关联对象的数据,lazy就是不获取么。
我只能说,大概是对的。
我们看代码
在Person里面修改OneToMany的属性。
@OneToMany(mappedBy="person",fetch=FetchType.EAGER)
public Set<Dream> getDreams() {
return dreams;
}
此时再运行代码6,发的sql语句就是:
select
person0_.id as id1_1_,
person0_.myname as myname1_1_,
dreams1_.personId as personId3_,
dreams1_.id as id3_,
dreams1_.id as id0_0_,
dreams1_.description as descript2_0_0_,
dreams1_.personId as personId0_0_
from
Person person0_
left outer join
Dream dreams1_
on person0_.id=dreams1_.personId
where
person0_.id=?
我们就能知道,如果想在取一的时候同时取多的一方,就在一的一方上加上fetch=feachType.eager。
那么根据前面的代码,我们就能推测出来
在默认情况下
一的那一方的fetch是lazy
多的那一方的fetch是eager
用eager修饰关联关系:hibernate会发关联的sql
用lazy修饰关联关系:hibernate不会主动发关联sql
注意,我上面说的是 用lazy修饰关联关系:hibernate不会发主动发关联的sql
为什么说主动呢?看看下面的代码
我们改一改代码6
//代码7
public void testGetPerson() {
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
Person p = (Person)s.get(Person.class, 2);
System.out.println(p.getDreams().size());
s.getTransaction().commit();
}
此时不设置person的fetch值。(保持默认的lazy)
此时发的sql语句是:
Hibernate:
select
person0_.id as id1_0_,
person0_.myname as myname1_0_
from
Person person0_
where
person0_.id=?
Hibernate:
select
dreams0_.personId as personId1_,
dreams0_.id as id1_,
dreams0_.id as id0_0_,
dreams0_.description as descript2_0_0_,
dreams0_.personId as personId0_0_
from
Dream dreams0_
where
dreams0_.personId=?
此时我们可以得到一个结论,如果在session里,我们只是获得"一"的那一方,hibernate默认不会去取多的那一方;但是如果在session里,访问了获得的"一"里面"多"的那一方数据(就是访问了person里面的dream)。就会发关联sql。
如此一来,就有了一个比较尴尬的事了
不管我在一的那一方设不设立fetch=FetchType.eager,我在session里面获得多的那一方的时候,都是可以的。
此时,还不如不设置fetch=FetchType.eager呢,因为有的时候,我确实不需要获得多的那一方,如果一的那一方设置成eager,岂不是要多查询很多无用的数据。
再看一个例子:
//代码8
public void testGetPerson() {
testSavePerson();
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
Person p = (Person)s.get(Person.class, 2);
s.getTransaction().commit();
System.out.println(p.getDreams().size());
}
就是把获得多的那一方数据的代码放到了session的外面。
如果此时person那边还有fetch=FetchType.eager,那么一切OK
屏幕上输出:
Hibernate:
select
person0_.id as id1_1_,
person0_.myname as myname1_1_,
dreams1_.personId as personId3_,
dreams1_.id as id3_,
dreams1_.id as id0_0_,
dreams1_.description as descript2_0_0_,
dreams1_.personId as personId0_0_
from
Person person0_
left outer join
Dream dreams1_
on person0_.id=dreams1_.personId
where
person0_.id=?
2 //dream的size是2
可是如果我把fetch=FetchType.eager去掉,在运行代码8,就会报错:
<span style="color:#FF0000;">failed to lazily initialize a collection of role: com.bjsxt.hibernate.Person.dreams, no session or session was closed</span>
说的很清楚,session已经关闭了。
为什么呢?
我们知道,从person到dream,是一对多,而默认情况下,一对多的fetch是lazy的。
也就是说,正常情况下,取了pseron是不会再取dream。
我们注意代码7发出的sql,是两个。
现在我要获得多的那方的命令,跑到了sesssion的外面,也就是说在session关闭后再去数据库里运行sql,那铁定会报错喽。
我们再试试:
//代码9
public void testGetPerson() {
testSavePerson();
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
Person p = (Person)s.get(Person.class, 2);
s.getTransaction().commit();
System.out.println(p.getDreams().size());
s.getTransaction().commit();
}
此时的person的fetch还是默认的lazy。
是否会报错呢?自己试试吧。
关于取对象这部分,hibernate还是比较麻烦的,我认为最好的方法就是保持默认的情况,一旦有了问题再查api文档,或其他的资料。
那既然这样,我为什么还要写这篇博客呢?反正最好的方法就是保持默认情况嘛。
因为:
世之奇伟、瑰怪、非常之观,常在于险远,而人之所罕至焉,故非有志者不能至也。
感谢glt
hibernate关联对象的增删改查------查的更多相关文章
- hibernate关联对象的增删改查------增
本文可作为,北京尚学堂马士兵hibernate课程的学习笔记. 这一节,我们看看hibernate关联关系的增删改查 就关联关系而已,咱们在上一节已经提了很多了,一对多,多对一,单向,双向... 其实 ...
- Hibernate进行对象的增删改查
首先我们看看hibernate手动配置步骤 (这个了解一点就可以了,以后是不会自己全部手动配置的) 1. 创建WEB项目 2 下载hibernate-release-4.3.11.F ...
- Python之实例对象的增删改查
#实例对象的增删改查p1 = ChinesePeople('wangyue')#print (p1.__dict__) #查看实例对象的属性#print (p1.name)(p1.play_ball( ...
- ADO.NET 增删改、查
数据访问 对应命名空间:System.Data.SqlClient; SqlConnection:连接对象SqlCommand:命令对象SqlDataReader:读取器对象 CommandText: ...
- Hibernate入门案例及增删改查
一.Hibernate入门案例剖析: ①创建实体类Student 并重写toString方法 public class Student { private Integer sid; private I ...
- Struts2+Spring+Hibernate实现员工管理增删改查功能(一)之ssh框架整合
前言 转载请标明出处:http://www.cnblogs.com/smfx1314/p/7795837.html 本项目是我写的一个练习,目的是回顾ssh框架的整合以及使用.项目介绍: ...
- Hibernate——(2)增删改查
案例名称:Hibernate完成增删改查 案例描述:抽取出工具类并完成删除.修改.查询功能. 具体过程: 1.使用上面的例子(Hibernate--(1)Hibernate入门http://blog. ...
- Hibernate常用api以及增删改查
一 .API的定义 所谓的API全称就是(Application Programming Interface,应用程序编程接口).就是类库对外提供的接口.类.枚举.注解等元素. 如:JDK API ...
- 页面循环绑定(变量污染问题),js面向对象编程(对象属性增删改查),js字符串操作,js数组操作
页面循环绑定(变量污染问题) var lis = document.querySelectorAll(".ul li") for ( var i = 0 ; i < lis. ...
随机推荐
- Swift基础之两指拉动图片变大变小
我们在使用APP的时候,有时会发现有些图片可以通过两指进行放大.缩小,今天就实现这样的一种效果,比较简单,不喜勿喷.... var imageVi:UIImageView! = nil var ...
- JVM远程DEBUG(JPDA )
原理 1. JPDA简介 JPDA(Java Platform Debugger Architecture)为Java平台上的调试器定义了一个标准的体系结构.该体系结构包括3个主要组成部分:JVM T ...
- main函数之后的调用
main函数代表进程的主线程.程序开始执行时,系统为程序创建一个进程,main函数其实并不是首先被调用的函数,而是操作系统调用了C/C++运行期启动函数,该函数负责对C/C++ 运行期库进行初始化.它 ...
- C++语言编译系统提供的内部数据类型的自动隐式转换
C++语言编译系统提供的内部数据类型的自动隐式转换规则如下: 程序在执行算术运算时,低类型自动隐式转换为高类型. 在函数调用时,将实参值赋给形参,系统隐式的将实参转换为形参的类型,并赋值给形参. 函数 ...
- Android简易实战教程--第三十话《撕衣美女》
此篇邪恶一些,给单身屌丝发点"福利",通过图片的绘制,给美女脱掉衣服. 原理:图片覆盖图片,通过画笔对顶端的图片做一些特效处理,即手指触摸的地方,设置为透明.即可显示最底部的美女图 ...
- Android 使用DownloadManager进行版本更新的完整方案
在Android App都会有版本更新的功能,以前我们公司是用友盟SDK更新功能,自己服务器没有这样的功能.版本检测.Apk下载都是使用友盟.最近看到友盟的版本更新SDK文档:十月份更新功能将会停止服 ...
- actionbar完全解析(一)
Action Bar是一种新増的导航栏功能,在Android 3.0之后加入到系统的API当中,它标识了用户当前操作界面的位置,并提供了额外的用户动作.界面导航等功能.使用ActionBar的好处是, ...
- LMAX高并发系统架构
很早就看到过MF的这篇The LMAX Architecture,可是之前一来英文水平不够,二来确实看不懂- 今天有幸再次看到,一口气读完终于有所领悟. 1 Overall Architecture ...
- Spark技术内幕: Shuffle详解(三)
前两篇文章写了Shuffle Read的一些实现细节.但是要想彻底理清楚这里边的实现逻辑,还是需要更多篇幅的:本篇开始,将按照Job的执行顺序,来讲解Shuffle.即,结果数据(ShuffleMap ...
- hbase操作(shell 命令,如建表,清空表,增删改查)以及 hbase表存储结构和原理
两篇讲的不错文章 http://www.cnblogs.com/nexiyi/p/hbase_shell.html http://blog.csdn.net/u010967382/article/de ...