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

hibernate 懒加载

这篇文章将重点讨论为什么以及如何在应用程序中使用称为LAZY和EAGER加载的概念,以及如何使用Spring的Hibernate模板以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 举例说明了使用Hibernate模式进行延迟/延迟加载 。


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

hibernate 懒加载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/353642.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++ 关键字typeid

转载网址&#xff1a;http://www.cppblog.com/smagle/archive/2010/05/14/115286.aspx 在揭开typeid神秘面纱之前&#xff0c;我们先来了解一下RTTI&#xff08;Run-Time Type Identification&#xff0c;运行时类型识别&#xff09;&#xff0c;它使程序能够获取由基指针或引用…

使用Apache Camel进行负载平衡

在此示例中&#xff0c;我们将向您展示如何使用Apache Camel作为系统的负载平衡器。 在计算机世界中&#xff0c;负载均衡器是一种充当反向代理并在许多服务器之间分配网络或应用程序流量的设备。 负载平衡器用于增加容量&#xff08;并发用户&#xff09;和应用程序的可靠性。…

Java8-Guava实战示例

示例一&#xff1a; 跟示例三对比一下&#xff0c;尽量用示例三 List<InvoiceQueryBean> invoiceQueryBeanList new ArrayList<>(); List<String> invoices Lists.newArrayList(Iterators.transform(invoiceQueryBeanList.iterator(), new Function<Inv…

java项目构建部署包

博客分类&#xff1a; JAVA Java 工程在生产环境运行时&#xff0c;一般需要构建成一个jar&#xff0c;同时在运行时需要把依赖的jar添加到classpath中去&#xff0c;如果直接运行添加classpath很不方便&#xff0c;比较方便的是创建一个shell脚本。在公司项目中看到把工程代码…

不错的自学网站合集

一、网站类1、假期在家如何查找论文资料&#xff1f;只需登录中国图书馆http://t.cn/hYmDq&#xff08;需注册&#xff09;&#xff0c;即可免费下载各种期刊和学位论文2、全球免费开放的电子图书馆http://t.cn/h4hJUf3、给大家推荐个神网站&#xff0c;只要是外文书籍基本上都…

c++中关于字符串的读入——cin、getline、get、gtes(查询+思考+总结)

1、cin读入一个字符&#xff1a;char c;cin>>c;2、cin读入一个字符串&#xff1a;char s[10];cin >> s;&#xff08;c风格字符串&#xff09; string str;cin >> str;&#xff08;c的string&#xff09;3、cin.get()读入一个字符&#xff1a;char c;ccin.…

java文档注释和标题注释_Java注释:探究和解释

java文档注释和标题注释Java 5 SE的许多出色功能之一是Annotations构造的引入。 注释是一些标签&#xff0c;可以将其插入到程序源代码中&#xff0c;以使用某种工具对其进行处理并使其变得有意义。 注释处理工具通常使用&#xff08;Java 5 SE的&#xff09;Reflection API在J…

shell 脚本初步,启动可执行 jar 文件

可能很多同学在看到这篇文章的时候是第一次接触 shell 脚本。所以我们首先需要了解什么是 shell 脚本。在 Windows 里我们经常会看到一种扩展名为 .bat 的文件&#xff0c;它称为批处理文件。批处理文件的作用是把许多个命令放在一个文件里&#xff0c;当运行这个文件的时候就执…

使用Java创建DynamoDB表

在这篇文章中&#xff0c;我们将使用java方法在DynamoDB数据库上创建表。 在开始之前&#xff0c;我们需要安装本地dynamodb&#xff0c;因为我们要避免使用dynamodb的任何费用。 有一个以前的岗位上本地dynamodb。 如果您使用docker&#xff0c;则可以找到本地dynamodb映像&a…

表达式前后缀表达形式 [zz]

(2012-09-12 13:08:39) 转载▼标签&#xff1a; 杂谈 转自&#xff1a;http://blog.csdn.net/whatforever/article/details/673853835,15,,80,70,-,*,20,/ //后缀表达方式(((3515)*(80-70))/20&#xff09;25 //中缀表达方式 /,*,,35,15,-,80,70, 2…

引用:初探Sql Server 执行计划及Sql查询优化

引用:初探Sql Server 执行计划及Sql查询优化 原文:引用:初探Sql Server 执行计划及Sql查询优化初探Sql Server 执行计划及Sql查询优化 收藏MSSQL优化之————探索MSSQL执行计划作者&#xff1a;no_mIss最近总想整理下对MSSQL的一些理解与感悟&#xff0c;却一直没有心思和时间…

Cities

问题 C: Cities 时间限制: 1 Sec 内存限制: 128 MB提交: 87 解决: 61[提交][状态][讨论版][命题人:admin]题目描述 There are n cities in Byteland, and the ith city has a value ai. The cost of building a bidirectional road between two cities is the sum of their v…

spring观察者模式_Spring事件的观察者模式

spring观察者模式介绍 观察者模式的本质是“定义对象之间的一对多依赖关系&#xff0c;以便当一个对象改变状态时&#xff0c;其所有依赖关系都会被通知并自动更新”。 GoF。 观察者模式是发布/订阅模式的子集&#xff0c;它允许许多观察者对象查看事件。 可以在不同的情况下使…

Lombok,自动值和不可变项

我喜欢布兰登&#xff08;Brandon &#xff09;在博客文章中比较Project Lombok &#xff0c; AutoValue和Immutables的建议 &#xff0c;而这篇文章试图做到这一点。 我已经简要概述了Project Lombok &#xff0c; AutoValue和Immutables &#xff0c;但是这篇文章有所不同&am…

linux对于zombie的处理

(Linux基础)[僵尸进程处理] 今天在服务器上推送项目的时候&#xff0c;突然发现很卡。就用top查看了一下&#xff0c;果然此事不简单啊。 top - 10:39:16 up 20 days, 23:11, 2 users, load average: 1.13, 1.09, 1.03 Tasks: 204 total, 2 running, 196 sleeping, 1 sto…

POJ - 1847 Tram(dijkstra)

题意&#xff1a;有向图有N个点&#xff0c;当电车进入交叉口&#xff08;某点&#xff09;时&#xff0c;它只能在开关指向的方向离开。 如果驾驶员想要采取其他方式&#xff0c;他/她必须手动更换开关。当驾驶员从路口A驶向路口B时&#xff0c;他/她尝试选择将他/她不得不手动…

用interrupt()中断Java线程

Javathread 最近在学习Java线程相关的东西&#xff0c;和大家分享一下&#xff0c;有错误之处欢迎大家指正&#xff0e; 假如我们有一个任务如下&#xff0c;交给一个Java线程来执行&#xff0c;如何才能保证调用interrupt()来中断它呢&#xff1f; Java代码 class ATask imple…

activemq和jms_保证主题,JMS规范和ActiveMQ的消息传递

activemq和jms最近&#xff0c;一位客户要求我仔细研究ActiveMQ的“持久”消息的实现&#xff0c;它如何应用于主题以及在存在非持久订户的故障转移方案中会发生什么。 我已经了解到&#xff0c;JMS语义规定&#xff0c;即使面对消息代理提供程序故障&#xff0c;也只能保证主题…

JAVA分代收集机制详解

Java堆中是JVM管理的最大一块内存空间。主要存放对象实例。在JAVA中堆被分为两块区域&#xff1a;新生代&#xff08;young&#xff09;、老年代&#xff08;old&#xff09;。堆大小新生代老年代&#xff1b;&#xff08;新生代占堆空间的1/3、老年代占堆空间2/3&#xff09;新…

FizzBu​​zz Kata与Java流

在柔道练习仅几周之后&#xff0c;我的儿子感到无聊。 他抱怨说自己没有学任何东西&#xff0c;因为他一遍又一遍地做着同样的事情。 混淆学习和做新事物的不仅仅是幼儿。 例如&#xff0c;有多少软件开发人员通过执行kata或参加dojos来进行刻意练习的麻烦&#xff1f; 重复您…