我是Java Persistence API和Hibernate的新手。

Java Persistence API中的FetchType.LAZYFetchType.EAGER什么区别?


#1楼

我可能会考虑性能和内存利用率。 最大的不同是EAGER的提取策略允许无需会话就使用提取的数据对象。 为什么?
连接会话时,如果在对象中渴望标记数据,则将提取所有数据。 但是,在延迟加载策略的情况下,如果会话断开连接(在session.close()语句之后session.close() ,则延迟加载标记对象不会检索数据。 休眠代理可以完成所有这些操作。 渴望策略使数据在关闭会话后仍然可用。


#2楼

默认情况下,对于所有集合和映射对象,提取规则为FetchType.LAZY ,对于其他实例,遵循FetchType.EAGER策略。
简而言之, @OneToMany@ManyToMany关系不会@ManyToMany获取相关对象(集合和映射),但是检索操作是通过@OneToOne@ManyToOne的字段进行级联的。

(礼貌:-objectdbcom)


#3楼

@ drop-shadow(如果使用的是Hibernate),则可以在调用getStudents()方法时调用Hibernate.initialize()

Public class UniversityDaoImpl extends GenericDaoHibernate<University, Integer> implements UniversityDao {//...@Overridepublic University get(final Integer id) {Query query = getQuery("from University u where idUniversity=:id").setParameter("id", id).setMaxResults(1).setFetchSize(1);University university = (University) query.uniqueResult();***Hibernate.initialize(university.getStudents());***return university;}//...
}

#4楼

据我所知,两种类型的访存都取决于您的要求。

FetchType.LAZY是按需的(即,当我们需要数据时)。

FetchType.EAGER是即时的(即,在我们的要求到来之前,我们不必要地获取记录)


#5楼

FetchType.LAZYFetchType.EAGER都用于定义默认的提取计划 。

不幸的是,您只能为LAZY提取覆盖默认的提取计划。 EAGER的获取较不灵活,可能会导致许多性能问题 。

我的建议是限制使关联变得更EAGER的冲动,因为获取是查询时的责任。 因此,所有查询都应使用fetch指令来仅检索当前业务案例所需的内容。


#6楼

基本上,

LAZY = fetch when needed
EAGER = fetch immediately

#7楼

从Javadoc :

EAGER策略是对持久性提供程序运行时的要求,必须热切地获取数据。 LAZY策略向持久性提供程序运行时提供了提示,即首次访问数据时应延迟获取数据。

例如,渴望比懒惰更积极主动。 懒惰仅在首次使用时发生(如果提供者接受了提示),而急切的事情(可能)会被预先获取。


#8楼

有时您有两个实体,并且它们之间存在关系。 例如,您可能有一个名为“ University的实体,而另一个名为“ Student实体,而一所大学可能有许多学生:

University实体可能具有一些基本属性,例如id,名称,地址等,还有一个名为students的集合属性,该属性返回给定大学的学生列表:

public class University {private String id;private String name;private String address;private List<Student> students;// setters and getters
}

现在,当您从数据库加载大学时,JPA会为您加载其ID,名称和地址字段。 但是对于如何加载学生,您有两个选择:

  1. 要将其与其余字段一起加载(即急切地),或者
  2. 在调用大学的getStudents()方法时按需(即延迟)加载它。

当一所大学有很多学生时,将所有学生与大学一起加载是没有效率的,特别是在不需要他们的情况下,在这种情况下,您可以声明希望在实际需要的学生中加载。 这称为延迟加载。

这是一个示例,其中将students明确标记为渴望加载:

@Entity
public class University {@Idprivate String id;private String name;private String address;@OneToMany(fetch = FetchType.EAGER)private List<Student> students;// etc.
}

这是一个示例,其中将students明确标记为延迟加载:

@Entity
public class University {@Idprivate String id;private String name;private String address;@OneToMany(fetch = FetchType.LAZY)private List<Student> students;// etc.
}

#9楼

EAGER加载集合意味着在获取父项时将其完全获取。 因此,如果您拥有Course ,并且具有List<Student> ,则在获取Course将从数据库中获取所有学生。

另一方面, LAZY意味着仅当您尝试访问List才获取List的内容。 例如,通过调用course.getStudents().iterator() 。 调用List上的任何访问方法将启动对数据库的调用以检索元素。 这是通过在List (或Set )周围创建Proxy来实现的。 因此,对于您的惰性集合,具体类型不是ArrayListHashSet ,而是PersistentSetPersistentList (或PersistentBag


#10楼

Book.java

        import java.io.Serializable;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.ManyToOne;import javax.persistence.Table;@Entity@Table(name="Books")public class Books implements Serializable{private static final long serialVersionUID = 1L;@Id@GeneratedValue(strategy=GenerationType.IDENTITY)@Column(name="book_id")private int id;@Column(name="book_name")private String name;@Column(name="author_name")private String authorName;@ManyToOneSubject subject;public Subject getSubject() {return subject;}public void setSubject(Subject subject) {this.subject = subject;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthorName() {return authorName;}public void setAuthorName(String authorName) {this.authorName = authorName;}}

Subject.java

    import java.io.Serializable;import java.util.ArrayList;import java.util.List;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.OneToMany;import javax.persistence.Table;@Entity@Table(name="Subject")public class Subject implements Serializable{private static final long serialVersionUID = 1L;@Id@GeneratedValue(strategy=GenerationType.IDENTITY)@Column(name="subject_id")private int id;@Column(name="subject_name")private String name;/**Observe carefully i have mentioned fetchType.EAGER. By default its is fetchType.LAZY for @OneToMany i have mentioned it but not required. Check the Output by changing it to fetchType.EAGER*/@OneToMany(mappedBy="subject",cascade=CascadeType.ALL,fetch=FetchType.LAZY,
orphanRemoval=true)List<Books> listBooks=new ArrayList<Books>();public List<Books> getListBooks() {return listBooks;}public void setListBooks(List<Books> listBooks) {this.listBooks = listBooks;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}}

HibernateUtil.java

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {private static SessionFactory sessionFactory ;static {Configuration configuration = new Configuration();configuration.addAnnotatedClass (Com.OneToMany.Books.class);configuration.addAnnotatedClass (Com.OneToMany.Subject.class);configuration.setProperty("connection.driver_class","com.mysql.jdbc.Driver");configuration.setProperty("hibernate.connection.url", "jdbc:mysql://localhost:3306/hibernate");                                configuration.setProperty("hibernate.connection.username", "root");     configuration.setProperty("hibernate.connection.password", "root");configuration.setProperty("dialect", "org.hibernate.dialect.MySQLDialect");configuration.setProperty("hibernate.hbm2ddl.auto", "update");configuration.setProperty("hibernate.show_sql", "true");configuration.setProperty(" hibernate.connection.pool_size", "10");configuration.setProperty(" hibernate.cache.use_second_level_cache", "true");configuration.setProperty(" hibernate.cache.use_query_cache", "true");configuration.setProperty(" cache.provider_class", "org.hibernate.cache.EhCacheProvider");configuration.setProperty("hibernate.cache.region.factory_class" ,"org.hibernate.cache.ehcache.EhCacheRegionFactory");// configurationStandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());sessionFactory = configuration.buildSessionFactory(builder.build());}
public static SessionFactory getSessionFactory() {return sessionFactory;
}
}

Main.java

    import org.hibernate.Session;import org.hibernate.SessionFactory;public class Main {public static void main(String[] args) {SessionFactory factory=HibernateUtil.getSessionFactory();save(factory);retrieve(factory);}private static void retrieve(SessionFactory factory) {Session session=factory.openSession();try{session.getTransaction().begin();Subject subject=(Subject)session.get(Subject.class, 1);System.out.println("subject associated collection is loading lazily as @OneToMany is lazy loaded");Books books=(Books)session.get(Books.class, 1);System.out.println("books associated collection is loading eagerly as by default @ManyToOne is Eagerly loaded");/*Books b1=(Books)session.get(Books.class, new Integer(1));Subject sub=session.get(Subject.class, 1);sub.getListBooks().remove(b1);session.save(sub);session.getTransaction().commit();*/}catch(Exception e){e.printStackTrace();}finally{session.close();}}private static void save(SessionFactory factory){Subject subject=new Subject();subject.setName("C++");Books books=new Books();books.setAuthorName("Bala");books.setName("C++ Book");books.setSubject(subject);subject.getListBooks().add(books);Session session=factory.openSession();try{session.beginTransaction();session.save(subject);session.getTransaction().commit();}catch(Exception e){e.printStackTrace();}finally{session.close();}}}

检查Main.java的retrieve()方法。 当我们得到Subject时,它的集合listBooks (用@OneToMany注释)将被延迟加载。 但是,另一方面,用@ManyToOne注释的集合主题的与书相关的关联会@ManyToOne加载(对于@ManyToOne[default][1]fetchType=EAGER )。 我们可以通过将fetchType.EAGER放在@OneToMany Subject.java上或将fetchType.LAZY放在@ManyToOne中的@ManyToOne上来更改行为。


#11楼

公共枚举FetchType扩展java.lang.Enum定义用于从数据库中获取数据的策略。 EAGER策略是对持久性提供程序运行时的要求,必须热切地获取数据。 LAZY策略向持久性提供程序运行时提供了提示,即首次访问数据时应延迟获取数据。 该实现被允许急切地获取已为其指定LAZY策略提示的数据。 示例:@Basic(fetch = LAZY)受保护的字符串getName(){返回名称; }

资源


#12楼

LAZY:延迟获取子实体,即,在获取父实体时,它仅获取子实体的代理(由cglib或任何其他实用程序创建),并且当您访问子实体的任何属性时,它实际上是由休眠方式获取的。

EAGER:它会与父级一起获取子级实体。

为了更好地理解,请转到Jboss文档,或者您可以对应用程序使用hibernate.show_sql=true并检查由hibernate发出的查询。


#13楼

除非您显式标记Eager Fetch类型,否则Hibernate默认选择Lazy Fetch类型。 为了更加准确和简洁,可以将差异说明如下。

FetchType.LAZY =除非您通过getter方法调用它,否则不会加载关系。

FetchType.EAGER =这将加载所有关系。

这两种类型的利弊。

Lazy initialization可避免不必要的计算并减少内存需求,从而提高性能。

Eager initialization会占用更多内存,并且处理速度很慢。

话虽如此, 根据情况 ,可以使用这些初始化中的任何一种。


#14楼

我想将此注释添加到上面的“庆焕民”中。

假设您正在使用带有此简单架构师的Spring Rest:

控制器<->服务<->存储库

而且您想将一些数据返回到前端,如果您使用的是FetchType.LAZY ,则在将数据返回到控制器方法之后,您将得到一个异常,因为该会话在Service中已关闭,因此JSON Mapper Object无法获取数据。

有三种常见的解决方案,取决于设计,性能和开发人员:

  1. 最简单的方法是使用FetchType.EAGER ,以便该会话在控制器方法下仍然有效。
  2. 反模式解决方案,使会话一直存在直到执行结束,这在系统中是一个巨大的性能问题。
  3. 最佳实践是将FetchType.LAZY与转换器方法一起使用,以将数据从Entity传输到另一个数据对象DTO并将其发送到控制器,因此,如果会话关闭,也不例外。

Java Persistence API中的FetchType LAZY和EAGER之间的区别?相关推荐

  1. Java Persistence API:快速入门

    各位读者好! 在我的一些朋友提出无数请求之后,我决定写一篇关于Java Persistence API的简短文章. 面向对象的编程范式是当​​今最流行和使用最广泛的模型,它具有无缝建模现实生活实体的能 ...

  2. fetchtype 动态控制_hibernate 中 fetch=FetchType.LAZY 懒加载失败处理方法

    对这种懒加载问题,最后的做法是利用Spring提供的一个针对Hibernate的一个支持类,其主要意思是在发起一个页面请求时打开Hibernate的Session,一直保持这个Session,使得Hi ...

  3. 什么是JPA(Java persistence API)?

    通常所说的jpa指的是啥? 1. JPA概念 Java persistence API 的简称,中文名是Java持久层API,是JDK5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象 ...

  4. 5 Hibernate:Java Persistence API (JPA) 入门

    Java Persistence API (JPA),Java 持久层 API,是 JCP 组织发布的 Java EE 标准规范,通过注解或 XML 描述实体对象和数据库表的映射关系. Hiberna ...

  5. JPA(Java Persistence API )

    ORM概述 ORM(Object-Relational Mapping) 表示对象关系映射.在面向对象的软件开发中,通过ORM,就可以把对象映射到关系型数据库中.只要有一套程序能够做到建立对象与数据库 ...

  6. 解析java中方法的重载和重写之间的区别与联系

    解析java中方法的重载和重写之间的区别与联系 1 不同点 1.1 方法重写是在不同的类中(父子类),方法重载是在同一类中 1.2 方法重载最初的目的是构造方法的多样化,方法重写的目的是让重写的方法满 ...

  7. IO多路复用中select、poll、epoll之间的区别

    本文来说下IO多路复用中select.poll.epoll之间的区别 文章目录 什么是IO多路复用 为什么有IO多路复用机制 同步阻塞(BIO) 同步非阻塞(NIO) IO多路复用(现在的做法) 3种 ...

  8. Java注解@Mock和@InjectMocks及@Mock和@Spy之间的区别

    Java注解@Mock和@InjectMocks及@Mock和@Spy之间的区别 1.@Mock和@InjectMocks的区别 @Mock为您需要的类创建一个模拟实现. @InjectMocks创建 ...

  9. SQL Server中唯一索引和唯一约束之间的区别

    This article gives you an overview of Unique Constraints in SQL and also the Unique SQL Server index ...

最新文章

  1. 闲话机器人领域的国际会议
  2. 深入浅出Spring Security(三):FilterChainProxy的运行过程
  3. Xmanager7如何通过SSH连接远程服务器
  4. 深刻揭示Python 与C/C++互动
  5. 学生系统优化(二)- - 窗体代码
  6. ubunut 下关闭apache服务自动启动
  7. Adaboost 2
  8. python标签使用教程_怎样用Python做标签云
  9. Python3.10 结构化模式匹配 PEP 634
  10. Vue笔记-Ant Design Vue构建前端连接后端WebSocket
  11. python 集合技巧
  12. 用python turtle画龙猫_【跟着弹簧学画画】教你一步步画出一只超萌的龙猫来!...
  13. [转载]sed实现直接修改文件内容
  14. fiddler的设置与简单使用
  15. ThinkPHP 漏洞检测
  16. 头歌——c++单向链表
  17. 植入大脑电极,晚期渐冻症患者通过神经信号交流!匹配准确率80%,有效时间仅1/3...
  18. 微信小程序-如何解决view中放纯数字或字母不会自动换行?【亲测有效】
  19. 编程中的命名设计那点事
  20. (附源码)Node.js自我展示博客网站 毕业设计231547

热门文章

  1. 解决Android 编译出错 找不到android.databinding.ViewDataBinding的类文件
  2. iOS进阶之协议Protocol(13)
  3. swift_025(Swift 的自动引用计数(ARC)
  4. WPF MVVM从入门到精通1:MVVM模式简介
  5. java并发编程基础—生命周期与线程控制
  6. phpstudy集成环境安装redis扩展
  7. Tomcat启动项目时内存溢出问题如何解决
  8. 第一讲 网络安全概述笔记
  9. 点在多边形内的判断(射线法)
  10. [转载] 理解RESTful架构