懒加载LAZY和实时加载EAGER的概念,在各种开发语言中都有广泛应用。其目的是实现关联数据的选择性加载,懒加载是在属性被引用时,才生成查询语句,抽取相关联数据。而实时加载则是执行完主查询后,不管是否被引用,立马执行后续的关联数据查询。社区里有人认为懒加载这种功能比较鸡肋,这种事仁者见仁,智者见智啦,个人觉得依自己业务场景而定。

顺带说一句,使用懒加载来调用关联数据,必须要保证主查询session(数据库连接会话)的生命周期没有结束,否则,你是无法抽取到数据的。在Spring Data JPA中如何自己控制session的生命周期,这个功能我还没有研究,作为下一次的研究课题。

在今天解析懒加载与实时加载的实例时,需要借助实体关系映射功能,配置实体间的一对多(OneToMany)和多对一(ManyToOne)关系。当然,还有OneToOne、ManyToMany关系,这个如有兴趣大家就自己研究下了。

一、为实体类ProcessBlock和Node添加一对多的关联关系。在我这个示例中ProcessBlock是流程定义类,一个流程定义对应多个流程节点,即Node表。下面给出代码。

1、ProcessBlock实体定义

@Entity(name = "nbpm_processblock" )

@NamedQuery(name = "ProcessBlock.findByName", query = "select p from nbpm_processblock p where p.name=?1" ) public class ProcessBlock implements Serializable { private static final long serialVersionUID = 1L ;

@Id

@Column(name = "id" ) long id;

@Column(name = "name" )

String name;

@Column(name = "description" )

String description; @OneToMany(mappedBy ="processblock",cascade=CascadeType.ALL,fetch = FetchType.EAGER) Set nodeSet = new HashSet (); public long getId() { return id;

}

……

定义Set属性 nodeSet,为其添加注解@OneToMany,意思就是一个ProcessBlock实体对应多个Node节点。注解属性 mappedBy,是指关联关系可以从Node类中的processblock属性上获取;cascade属性设置成CascadeType.ALL,是说主从表全面建立级联关系;fetch属性设置成FetchType.EAGER,是指加载规则是即时加载。查看源码会发现默认情况下,OneToMany注解的fetch属性设置的是FetchType.LAZY。

2、Node实体定义

@Entity(name = "nbpm_node" ) public class Node implements Serializable { private static final long serialVersionUID = 1L ;

@Id

@Column(name = "id" ) long id;

@Column(name = "name" )

String name;

@Column(name = "description" )

String description;

@Column(name = "subclass" )

String subclass; /** * 关联关系必须存在 */ @ManyToOne(optional = true )

@JoinColumn(name ="processblock" )

ProcessBlock processblock; public long getId() { return id;

}

……

定义ProcessBlock属性 processblock,为其添加注解@ManyToOne,意思就是一个Node实体对应一个ProcessBlock流程定义。添加注解@JoinColumn,属性name设置成"processblock",意思是nbpm_node表中的processblock字段是外键,与ProcessBlock的主键建议关联关系。需要说明一下 ManyToOne注解的fetch属性 默认是FetchType.EAGER,查询时会立马抽取对应的主表数据。这块的考虑还是很细致的,大致就是关联数据是集合时就懒加载,是单条数据时就实时加载。

二、编写查询示例并展示结果。查询使用自定义的JpaUtil工具,工具实现请参考 《自定义JpaUtil,快速完成Hql执行逻辑(一)》

1、查询ProcessBlock,主干流程数据,因为设置的nodeSet属性是实时加载加载,查询完成,断点查看确实拿到了流程对应的所有节点信息。

Map params = new HashMap<> ();

params.put( "name", "主干流程" ); List list = ApplicationContextUtil.instance.getJpaUtil().list( "select u from simm.spring.entity.ProcessBlock u where u.name=:name", params, ProcessBlock. class ); Set nodes = list.get(0).getNodeSet();

-- Hibernate框架生成的查询语句 ----------------- Hibernate: select processblo0_.id as id1_2_, processblo0_.description as descript2_2_, processblo0_.name as name3_2_ from nbpm_processblock processblo0_ where processblo0_.name = ?

Hibernate: select nodeset0_.processblock as processb5_1_0_, nodeset0_.id as id1_1_0_, nodeset0_.id as id1_1_1_, nodeset0_.description as descript2_1_1_, nodeset0_.name as name3_1_1_,

nodeset0_.processblock as processb5_1_1_, nodeset0_.subclass as subclass4_1_1_ from nbpm_node nodeset0_ where nodeset0_.processblock = ?

Hibernate: select nodeset0_.processblock as processb5_1_0_, nodeset0_.id as id1_1_0_, nodeset0_.id as id1_1_1_, nodeset0_.description as descript2_1_1_, nodeset0_.name as name3_1_1_,

nodeset0_.processblock as processb5_1_1_, nodeset0_.subclass as subclass4_1_1_ from nbpm_node nodeset0_ where nodeset0_.processblock = ?

Hibernate: select nodeset0_.processblock as processb5_1_0_, nodeset0_.id as id1_1_0_, nodeset0_.id as id1_1_1_, nodeset0_.description as descript2_1_1_, nodeset0_.name as name3_1_1_,

nodeset0_.processblock as processb5_1_1_, nodeset0_.subclass as subclass4_1_1_ from nbpm_node nodeset0_ where nodeset0_.processblock = ?

Hibernate: select nodeset0_.processblock as processb5_1_0_, nodeset0_.id as id1_1_0_, nodeset0_.id as id1_1_1_, nodeset0_.description as descript2_1_1_, nodeset0_.name as name3_1_1_,

nodeset0_.processblock as processb5_1_1_, nodeset0_.subclass as subclass4_1_1_ from nbpm_node nodeset0_ where nodeset0_.processblock = ?

2、将ProcessBlock类的属性nodeSet设置成懒加载LAZY,查询后,发现对应的节点列表信息获取不到了。这里懒加载的数据读取不到是因为主查询的session已经结束。

@OneToMany(mappedBy="processblock",cascade=CascadeType.ALL,fetch = FetchType.LAZY ) // @JoinColumn(name="processblock_id") Set nodeSet = new HashSet();

-- Hibernate框架生成的查询语句 ----------------- Hibernate: select processblo0_.id as id1_2_, processblo0_.description as descript2_2_, processblo0_.name as name3_2_ from nbpm_processblock processblo0_ where processblo0_.name = ?

3、Hql直接查询关联属性

List nodeList = ApplicationContextUtil.instance.getJpaUtil().list( "select u.nodeSet from simm.spring.entity.ProcessBlock u where u.id=1", null , Node. class );

-- Hibernate框架生成的查询语句 ----------------- Hibernate: select nodeset1_.id as id1_1_, nodeset1_.description as descript2_1_, nodeset1_.name as name3_1_, nodeset1_.processblock as processb5_1_, nodeset1_.subclass as subclass4_1_

nbpm_processblock processblo0_ inner join nbpm_node nodeset1_ on processblo0_.id = nodeset1_.processblock where processblo0_.id = 1 Hibernate: select processblo0_.id as id1_2_0_, processblo0_.description as descript2_2_0_, processblo0_.name as name3_2_0_ from nbpm_processblock processblo0_ where processblo0_.id = ?

至此,本次测试的主要内容就说完了,调试细节比较繁杂这里不再细表。在最后有个疑问与大家交流下,在ManyToOne这个注解中有一个optional的属性,源码里标注该属性默认设置成true,即与主表间的关联可以为null,设置成false时,则关联关系不能为空。我猜想着设置此关系后,生成的sql语句可能会有所不同,或者会引起系统运行时报错什么的。但是测试发现,并没有影响,sql语句都是left outer join关联,设置成false时,空关系也不会造成报错,似乎没有作用,调试源码暂时还没有发现其调用逻辑。有道友知道这个功能吗?可以帮我解答一下,谢谢!

hql懒加载后判断对象是否存在_JPA数据懒加载LAZY和实时加载EAGER(二) - Mr.Simm - 博客园...相关推荐

  1. hql懒加载后判断对象是否存在_hibernate延迟加载(懒加载)详解

    延迟加载 一.什么是懒加载?他的作用? 延迟加载,也叫懒加载,它是Hibernate为提高程序执行效率而提供的一种机制,即只有真正使用该对象的数据时才会创建. Hibernate中主要是通过代理(pr ...

  2. ajax自动加载blogjava和博客园的rss

    自动加载blogjava和博客园的rss <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"   "h ...

  3. 博客园自定义页面风格设计 后续篇(页面设计模式及代码高亮 鼠标点击效果升级)...

    前言 在之前所写过的博客园自定义页面风格设计篇中,我们已经说明了其中两种风格的页面设计,鼠标图案的修改,公告栏的设置,背景音乐的制作,关于CSS以及用Canvas和requestAnimFrame做动 ...

  4. 给博客园加一个会动的小人-spig.js

    给博客园加一个会动的小人-spig.js 效果大概是这样,感觉十分可爱qvq 那么怎么添加呢? 首先需要开通js/html权限. 然后在页脚html代码中加入以下代码 <script src=& ...

  5. 改进博客园Markdown显示功能(加代码行号、显示代码所用编程语言)

    博客园的markdown模式下的代码高亮功能使用的是highlight.js,没有行号和显示相应编程语言的功能,只好自己将其改造了一下(将这两种功能一并实现了)~ 先看一下效果,再详细介绍方法~ 查看 ...

  6. 10000个怎么用js写 创建li_给博客园加一个会动的小人-spig.js

    给博客园加一个会动的小人-spig.js 效果大概是这样,感觉十分可爱qvq 那么怎么添加呢? 首先需要开通js/html权限. 然后在页脚html代码中加入以下代码 -- var isindex=t ...

  7. html加css作品,我的影视作品,如何在博客园发布带有CSS样式的HTML

    总结一下,我做过的视频:(顺便试试在博客园如何发HTML网页) 发布网页总结: HTML可以正常发送,但最好将你要发布的html文件放在一个带有ID的div中,这样方便后期添加样式时通过ID添加,不会 ...

  8. java用正则表达式判断字符串中是否仅包含英文字母、数字和汉字_灵思致远Leansmall的博客-CSDN博客_java判断字符串只包含数字字母

    import java.util.regex.Matcher; import java.util.regex.Pattern;public class StrValidate {// 纯数字priva ...

  9. 博客园主页样式修改(加透明背景和微调位置)

    背景透明方法 主要就是以下两个好用点.但是有区别.前者不继承透明,后者继承透明. background:rgba(255,255,255,0.5); optcity:0.5 参阅资料:https:// ...

  10. 解决博客园添加hexo看板娘无法加载问题

    关于添加看板娘 因为觉得作者设置的页面左下角的网易云音乐并不实用所以将其改成看板娘 但是由于太菜,不能很好的理解live2d的官方文档 数次度娘都是一些不能用的版本,不是配置少双引号,就是路径错误,看 ...

最新文章

  1. 工具分享-自动生成正则表达式的各种代码,附带正则表达式介绍
  2. [CSS]复选框单选框与文字对齐问题的研究与解决.
  3. LYDSY模拟赛day2 Divisors
  4. java web中验证码的实现
  5. 01-H5语义化标签
  6. 为什么代码规范要求SQL语句不要过多的join?
  7. matlab predict函数并行,Matalb 智能算法第29个案例运行报错问题
  8. 《数字视频和高清:算法和接口》一2.6消费类电子显示器
  9. 博客园修改TinyMCE编辑器为Markdown编辑器的方法
  10. ASP导出到Excel
  11. 又遇到jqGrid在chrome下宽度不正常有滚动条
  12. USB3300速度调试
  13. 流行编曲(6)副旋律&合声
  14. 女解码高手王小云:十年破译五部顶级密码(图)
  15. 元数据编码和传输标准(METS)
  16. js直接打印pdf文件内容
  17. 6.4 二项式系数和恒等式
  18. 计算机音乐来自天堂的魔鬼,来自天堂的魔鬼
  19. 计算广告——广告定向实践
  20. 无线网首选dns服务器怎么设置,dns服务器设置(192.168.1.1的首选dns)

热门文章

  1. plot sin 03-数据区域边界线的位置
  2. Eclipse SQL Explorer
  3. 【Spring-tx】ProxyTransactionManagementConfiguration类
  4. springboot的if else过多解决方案
  5. Spring IOC源码笔记(三)
  6. Delphi -- 农历算法
  7. win和linux下DBI安装手册
  8. 关于Chrome浏览器(Chrome Stable、 Chrome Canary 、Chromium)
  9. JavaScript专题之跟着 underscore 学节流
  10. ArcGIS图层和要素的过滤显示