原文:https://www.cnblogs.com/MrSi/p/8081811.html

懒加载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<Node> nodeSet = new HashSet<Node>();
public long getId() {
return id;
}
……

  定义Set<Node>属性 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<String, Object> params = new HashMap<>();
params.put("name", "主干流程");
List<ProcessBlock> list = ApplicationContextUtil.instance.getJpaUtil().list(
"select u from simm.spring.entity.ProcessBlock u where u.name=:name", params, ProcessBlock.class
); Set<Node> 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<Node> nodeSet = new HashSet<Node>();

   

-- 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<Node> 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=?

JPA数据懒加载LAZY和实时加载EAGER(转)的更多相关文章

  1. JPA数据懒加载LAZY和实时加载EAGER(二)

    懒加载LAZY和实时加载EAGER的概念,在各种开发语言中都有广泛应用.其目的是实现关联数据的选择性加载,懒加载是在属性被引用时,才生成查询语句,抽取相关联数据.而实时加载则是执行完主查询后,不管是否 ...

  2. JPA数据懒加载LAZY配合事务@Transactional使用(三)

    上篇博文<JPA数据懒加载LAZY和实时加载EAGER(二)>讲到,如果使用懒加载来调用关联数据,必须要保证主查询session(数据库连接会话)的生命周期没有结束,否则,你是无法抽取到数 ...

  3. JPA的懒加载

    JPA数据懒加载LAZY和实时加载EAGER(二)   懒加载LAZY和实时加载EAGER的概念,在各种开发语言中都有广泛应用.其目的是实现关联数据的选择性加载,懒加载是在属性被引用时,才生成查询语句 ...

  4. DevExpress的GridControl的实时加载数据解决方案(取代分页)

    http://blog.csdn.net/educast/article/details/4769457 evExpress是一套第三方控件 其中有类似DataGridView的控件 今天把针对Dev ...

  5. Swift - 懒加载(lazy initialization)

    Swift中是存在和OC一样的懒加载机制的,在程序设计中,我们经常会使用 懒加载 ,顾名思义,就是用到的时候再开辟空间 懒加载 格式: lazy var 变量: 类型 = { 创建变量代码 }() 懒 ...

  6. Swift 懒加载(lazy) 和 Objective-C 懒加载的区别

    在程序设计中,我们经常会使用 懒加载 ,顾名思义,就是用到的时候再开辟空间,比如iOS开发中的最常用控件UITableView,实现数据源方法的时候,通常我们都会这样写 Objective-C - ( ...

  7. iOS 开发——实用技术Swift篇&Swift 懒加载(lazy)

    Swift 懒加载(lazy) 在程序设计中,我们经常会使用 * 懒加载 * ,顾名思义,就是用到的时候再开辟空间,比如iOS开发中的最常用控件UITableView,实现数据源方法的时候,通常我们都 ...

  8. Swift中懒加载(lazy initialization)的实现

    Swift中是存在和OC一样的懒加载机制的,但是这方面国内的资料比较少,今天把搜索引擎换成了Bing后发现用Bing查英文\最新资料要比百度强上不少. 我们在OC中一般是这样实现懒加载初始化的: 1: ...

  9. js图片实时加载

    浏览大型网站,特别是图片比较多的图片,如大型的电商网站,你会发现处了第一屏外,往下滚动的时候图片才加载出来,没必要一开始加载就要把全部图片加载出来,这样子打开网面的速度得到了很好提高.以下是笔者目前所 ...

随机推荐

  1. SQL SERVER2014 安装 Error code 0x858C001B.

    原因是语言版本不一致,SQL SERVER是中文简体版,操作系统是英文版,在操作系统.控制面板,区域语言设置为中文就Ok啦. TITLE: SQL Server Setup failure.----- ...

  2. Nginx Windows 安装启动

    原文连接:http://tengine.taobao.org/book/appendix_c.html#nginxwindows 下载 Nginx是开源软件,用户可以访问 http://nginx.o ...

  3. 遍历python字典几种方法

    遍历python字典几种方法 from: http://ghostfromheaven.iteye.com/blog/1549441 aDict = {'key1':'value1', 'key2': ...

  4. Shiro权限总结

    参考学习地址   shiro 瞅完就会用(ssm+shiro)    Spring Shiro配置实现用户认证和授权 anon:它对应的过滤器里面是空的,什么都没做,另外.do和.jsp后面的*表示参 ...

  5. 不影响Inspector布局拓展类

    DecoratorEditor.cs using System.Collections.Generic; using System.Linq; using System.Reflection; usi ...

  6. Social media users of the world unite!

    Social media users of the world unite!全世界社交媒体用户联合起来!If Plato were alive today, he might well regard ...

  7. oracle 理解执行计划

    ·BUFFER SORT是BUFFER却不是SORT 用AUTOTRACE查看执行的计划的同学常问到执行计划里的BUFFER SORT是什么意思,这里为什么要排序呢? BUFFER SORT不是一种排 ...

  8. java script 模拟鼠标事件

    try { var selector1 = "._3-8y:first-child"; var evt = document.createEvent("MouseEven ...

  9. Django入门-框架目录介绍

    Django入门博客:https://www.cnblogs.com/chuangming/p/9076721.html#4098510 备注:使用 Django 框架之后,开发服务端方便了很多.我们 ...

  10. cf-Round542-Div2-C(暴力+DFS)

    题目链接:http://codeforces.com/contest/1130/problem/C 思路: 利用DFS搜索(r1,c1)和(r2,c2)可到达的点的集合,分别存在a1,a2中,若a1= ...