这篇文章将重点讨论为什么以及如何在应用程序中使用称为LAZY和EAGER加载的概念,以及如何使用Spring的休眠模板以EAGER方式加载LAZY实体。

当然,正如标题本身所暗示的那样,我们将通过一个示例来说明这一点。 场景就是这样;

您是一个有很多玩具的孩子的父母。 但是当前的问题是,只要您打电话给他(我们假设您有一个男孩),他也会带着所有玩具来找您。 现在这是一个问题,因为您不希望他一直都随身携带玩具。

因此,作为理论上的父母,您会继续前进,并将孩子的玩具定义为LAZY。 现在,每当您打电话给他时,他都会不带玩具来到您身边。

但是您面临另一个问题。 当需要进行家庭旅行时,您希望他带上他的玩具,因为否则孩子会厌倦这次旅行。 但是,由于您对孩子的玩具严格执行LAZY,因此您无法要求他随身携带玩具。 这是EAGER提取起作用的地方。 首先让我们看看我们的领域类。

package com.fetchsample.example.domain;import java.util.HashSet;
import java.util.Set;import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;/*** Holds information about the child* * @author dinuka.arseculeratne* */
@Entity
@Table(name = 'CHILD')
@NamedQuery(name = 'findChildByName', query = 'select DISTINCT(chd) from Child chd left join fetch chd.toyList where chd.childName=:chdName')
public class Child {public static interface Constants {public static final String FIND_CHILD_BY_NAME_QUERY = 'findChildByName';public static final String CHILD_NAME_PARAM = 'chdName';}@Id@GeneratedValue(strategy = GenerationType.AUTO)/*** The primary key of the CHILD table*/private Long childId;@Column(name = 'CHILD_NAME')/*** The name of the child*/private String childName;@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)/*** The toys the child has. We do not want the child to have the same toy more than* once, so we have used a set here.*/private Set<Toy> toyList = new HashSet<Toy>();public Long getChildId() {return childId;}public void setChildId(Long childId) {this.childId = childId;}public String getChildName() {return childName;}public void setChildName(String childName) {this.childName = childName;}public Set<Toy> getToyList() {return toyList;}public void addToy(Toy toy) {toyList.add(toy);}}
package com.fetchsample.example.domain;import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;/*** Hols data related to the toys a child possess* * @author dinuka.arseculeratne* */
@Entity
@Table(name = 'TOYS')
public class Toy {@Id@GeneratedValue(strategy = GenerationType.AUTO)@Column(name = 'TOY_ID')/*** The primary key of the TOYS table*/private Long toyId;@Column(name = 'TOY_NAME')/*** The name of the toy*/private String toyName;public Long getToyId() {return toyId;}public void setToyId(Long toyId) {this.toyId = toyId;}public String getToyName() {return toyName;}public void setToyName(String toyName) {this.toyName = toyName;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + ((toyName == null) ? 0 : toyName.hashCode());return result;}@Override/*** Overriden because within the child class we use a Set to* hold all unique toys*/public boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Toy other = (Toy) obj;if (toyName == null) {if (other.toyName != null)return false;} else if (!toyName.equals(other.toyName))return false;return true;}@Overridepublic String toString() {return 'Toy [toyId=' + toyId + ', toyName=' + toyName + ']';}}

如您所见,我们有两个简单的实体分别代表孩子和玩具。 这个孩子与这些玩具有一对多的关系,这意味着一个孩子可以拥有许多玩具(哦,我多么想念我的童年时代)。 之后,我们需要与数据进行交互,因此让我们继续定义DAO(数据访问对象)接口和实现。

package com.fetchsample.example.dao;import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;import com.fetchsample.example.domain.Child;/*** The basic contract for dealing with the {@link Child} entity* * @author dinuka.arseculeratne* */
@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
public interface ChildDAO {/*** This method will create a new instance of a child in the child table* * @param child*            the entity to be persisted*/public void persistChild(Child child);/*** Retrieves a child without his/her toys* * @param childId*            the primary key of the child table* @return the child with the ID passed in if found*/public Child getChildByIdWithoutToys(Long childId);/*** Retrieves the child with his/her toys* * @param childId*            the primary key of the child table* @return the child with the ID passed in if found*/public Child getChildByIdWithToys(Long childId);/*** Retrieves the child by the name and with his/her toys* * @param childName*            the name of the child* @return the child entity that matches the name passed in*/public Child getChildByNameWithToys(String childName);}
package com.fetchsample.example.dao.hibernate;import org.springframework.orm.hibernate3.support.HibernateDaoSupport;import com.fetchsample.example.dao.ChildDAO;
import com.fetchsample.example.domain.Child;/*** The hibernate implementation of our {@link ChildDAO} interface* * @author dinuka.arseculeratne* */
public class ChildDAOHibernateImpl extends HibernateDaoSupport implementsChildDAO {/*** {@inheritDoc}*/public void persistChild(Child child) {getHibernateTemplate().persist(child);}/*** {@inheritDoc}*/public Child getChildByIdWithoutToys(Long childId) {return getHibernateTemplate().get(Child.class, childId);}/*** {@inheritDoc}*/public Child getChildByIdWithToys(Long childId) {Child child = getChildByIdWithoutToys(childId);/*** Since by default the toys are not loaded, we call the hibernate* template's initialize method to populate the toys list of that* respective child.*/getHibernateTemplate().initialize(child.getToyList());return child;}/*** {@inheritDoc}*/public Child getChildByNameWithToys(String childName) {return (Child) getHibernateTemplate().findByNamedQueryAndNamedParam(Child.Constants.FIND_CHILD_BY_NAME_QUERY,Child.Constants.CHILD_NAME_PARAM, childName).get(0);}}

一个简单的合同。 我有四种主要方法。 当然,第一个只是将子实体持久化到数据库中。

第二种方法通过传入的主键来检索Child,但不提取玩具。

第三种方法首先获取Child,然后使用Hibernate模板的initialize()方法检索Child的玩具。 请注意,当您调用initialize()方法时,hibernate将把您LAZY定义的集合获取到您检索的Child代理中。

最终方法还可以检索“儿童”的玩具,但这一次使用命名查询。 如果返回到Child实体的Named查询,则可以看到我们使用了“ left join fetch ”。 当返回有资格的Child实体时,实际上是关键字fetch也会初始化玩具集合。 最后,我有我的主班来测试我们的功能;

package com.fetchsample.example;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.fetchsample.example.dao.ChildDAO;
import com.fetchsample.example.domain.Child;
import com.fetchsample.example.domain.Toy;/*** A test class* * @author dinuka.arseculeratne* */
public class ChildTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext('com/fetchsample/example/spring-context.xml');/*** First we initialize a child*/Child child = new Child();/*** A cool ben 10 action figure*/Toy ben10 = new Toy();ben10.setToyName('Ben 10 figure');/*** A even more cooler spider man action figure*/Toy spiderMan = new Toy();spiderMan.setToyName('Spider man figure');child.setChildName('John');/*** Add the toys to the collection*/child.addToy(ben10);child.addToy(spiderMan);ChildDAO childDAO = (ChildDAO) context.getBean('childDAO');childDAO.persistChild(child);Child childWithoutToys = childDAO.getChildByIdWithoutToys(1L);// The following line will throw a lazy initialization error since we have// defined fetch type as LAZY in the Child domain class.// System.out.println(childWithToys.getToyList().size());Child childWithToys = childDAO.getChildByIdWithToys(1L);System.out.println(childWithToys.getToyList().size());Child childByNameWithToys = childDAO.getChildByNameWithToys('John');System.out.println(childByNameWithToys.getToyList().size());}
}

将基础实体定义为LAZY是一种好习惯,因为在很多情况下,您可能不希望实体内的集合,而只想与基础实体中的数据进行交互。 但是,如果需要集合的数据,则可以使用前面提到的任何一种方法。

今天就是这样。 对于任何想尝试该示例的人,我都在这里上传了该示例。

参考: “ 我的旅程” IT博客中的JCG合作伙伴 Dinuka Arseculeratne 举例说明了使用休眠模式进行延迟/延迟加载 。

翻译自: https://www.javacodegeeks.com/2012/08/hibernate-lazyeager-loading-example.html

Hibernate懒/急加载示例相关推荐

  1. hibernate 懒加载_Hibernate懒/急加载示例

    hibernate 懒加载 这篇文章将重点讨论为什么以及如何在应用程序中使用称为LAZY和EAGER加载的概念,以及如何使用Spring的Hibernate模板以EAGER方式加载LAZY实体. 当然 ...

  2. FetchType.LAZY和FetchType.EAGER什么区别?(懒加载和急加载的理解)

    1.FetchType.LAZY:懒加载,加载一个实体时,定义懒加载的属性不会马上从数据库中加载. 2.FetchType.EAGER:急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载. ...

  3. axios vue 加载效果动画_vue+axios+element ui 实现全局loading加载示例

    实现全局loading加载 分析需求,我们只需要在请求发起的时候开始loading,响应结束的时候关闭loading,就这么简单 对不对? import axios from 'axios'; imp ...

  4. Dagger2利器系列二:懒/重加载+Component 的组织关系

    目录 一:懒/重加载 1.1 Dagger2 中的懒加载 1.2 Provider 强制重新加载 二:Component 的组织依赖关系 2.1 前言 2.2 Component 的组织关系 2.2. ...

  5. superset加载示例数据load_examples报错

    项目场景: superset安装好后到了加载官方示例数据这一步,需要运行指令load_examples,但不知道是不是墙的原因,总是报一个无法连接的错. 问题描述: load_examples指令: ...

  6. jQuery图片懒加载示例(滚动函数再加载)

    图片懒加载可以极大的减轻服务器请求的负担,如果没有做这样的操作,一个页面很多图片同时请求,就会渲染慢,影响用户体验! 原理其实很简单,就是滚动条拉下来显示的时候再加载显示出真实的图片,在不显示的区域的 ...

  7. 【Android 内存优化】Bitmap 长图加载 ( BitmapRegionDecoder 简介 | BitmapRegionDecoder 使用流程 | 区域解码加载示例 )

    文章目录 一.BitmapRegionDecoder 简介 二.图片信息 三.BitmapRegionDecoder 对象创建 四.解码图像 五.图像区域解码示例 六.源码及资源下载 一.Bitmap ...

  8. 微信小程序下拉刷新真机没效果_微信小程序 下拉刷新 上拉加载(示例代码)

    1.下拉刷新 小程序页面集成了下拉功能,并提供了接口,我们只需要一些配置就可以拿到事件的回调. 1. 需要在 .json 文件中配置. 如果配置在app.json文件中,那么整个程序都可以下拉刷新.如 ...

  9. Hibernate懒加载问题的5种解决方案

    ** 1.Hibernate基础 ** Hibernate基础,传送门 ** 2.什么是Hibernate懒加载 ** 当我们查询一个对象的时候,在默认情况下,返回的只是该对象的代理对象,当用户去使用 ...

最新文章

  1. 它来了!ROS2从入门到精通:理论与实战
  2. 【Kotlin】Kotlin 语言集合中的高阶函数详解 ( 数据类 data class | maxBy | minBy | filter | map | any | count | find )
  3. 推送改变世界!Push提高用户活跃度的三不原则
  4. 丢弃commit_git丢弃本地修改的所有文件(新增、删除、修改)
  5. 学python最重要的是_Python学习,要选哪个版本?
  6. [ActionScript 3.0] AS3中的位图(BitmapData)应用
  7. 关于电脑安装多个版本JDK后使用时的切换
  8. SSZipArchive的使用详解和遇到的问题
  9. CodeForces 706A Beru-taxi
  10. git base cli
  11. 南开100题C语言(031-040)
  12. 远程springmvc ajax请求乱码,网络编程springMVC解决ajax请求乱码的三种方法
  13. 小程序实现图片双滑放大缩小
  14. uniapp修改html样式,关于css:uniapp操作dom改变css样式
  15. 视觉slam十四讲 pdf_《视觉SLAM十四讲》学习笔记+关键知识点汇总(一)
  16. 微信小程序布局移动电商之路
  17. 理解C#中装箱和拆箱的概念
  18. 三、自定义python库下有多个py脚本时,__init__.py的配置
  19. python富翁与穷人_富人家的孩子怎样看待穷人家的孩子?
  20. 渣画质视频秒变清晰,“达芬奇”工具集帮你自动搞定

热门文章

  1. java登录界面命令_Java命令行界面(第16部分):JArgp
  2. activiti 变量_如何在Activiti中使用瞬态变量
  3. lambda 分类聚合_使用Java 8 Lambda,流和聚合
  4. akka 消息发送接收_Akka型演员:探索接收器模式
  5. jax-rs/jersey_使用JAX-RS(Jersey)的HTTP状态错误消息响应中的自定义原因短语
  6. consul宕机配置丢失_简单的配置死机
  7. Spring Reactive已经过时了吗? 螺纹连接反转
  8. scala集合转java_Java,Scala,Guava和Trove集合-它们可以容纳多少数据?
  9. JDK 12,合并的收集器和命名的挑战
  10. java中重载 参数顺序_Java方法中的参数太多,第4部分:重载