Разница между FetchType LAZY и EAGER в Java Persistence API?
Я новичок в Java Persistence API и Hibernate.
В чем разница между FetchType.LAZY
и FetchType.EAGER
в Java Persistence API?
- Как обновить схемы таблиц базы данных с помощью генерации схемы NHibernate?
- Может ли Hibernate работать с синтаксисом «ON DUPLICATE KEY UPDATE» MySQL?
- Можно ли создавать модели django из базы данных?
- Ошибка гибернации: org.hibernate.NonUniqueObjectException: другой объект с тем же значением идентификатора уже был связан с сеансом
- Выполнение вложений и обновлений с помощью Dapper
- Ошибка: java.lang.NoSuchMethodError: org.objectweb.asm.ClassWriter. (I) V
- Как Hibernate обнаруживает грязное состояние объекта сущности?
- Entity Framework слишком медленная. Какие у меня варианты?
- Автоматическое резервирование зарезервированного слова для таблиц и столбцов Hibernate
- Каковы преимущества использования ORM?
- Объекты ORM и сущности домена в Entity Framework 6.0
- Hibernate: MyInterceptor # onFlushDirty никогда не вызывается
- Как использовать Hibernate @ Любые связанные annotations?
Иногда у вас есть две сущности, и между ними есть отношения. Например, у вас может быть объект под названием «Университет» и другой объект «Студент».
Учреждение университета может иметь некоторые основные свойства, такие как идентификатор, имя, адрес и т. Д., А также свойство, называемое учениками:
public class University { private String id; private String name; private String address; private List students; // setters and getters }
Теперь, когда вы загружаете университет из базы данных, JPA загружает для вас свои идентификаторы, имена и адреса. Но у вас есть два варианта для студентов: загрузить его вместе с остальными полями (то есть с нетерпением) или загрузить его по требованию (т.е. лениво), когда вы называете метод getStudents () университета.
Когда в университете много учеников, неэффективно загружать всех своих учеников, когда они не нужны. Поэтому в подобных случаях вы можете заявить, что хотите, чтобы ученики загружались, когда они действительно нужны. Это называется ленивой загрузкой.
В основном,
LAZY = fetch when needed EAGER = fetch immediately
EAGER
коллекций означает, что они извлекаются полностью в момент, когда их родитель получает. Итак, если у вас есть Course
и у него есть List
, все ученики будут извлечены из базы данных во время получения Course
.
LAZY
с другой стороны, означает, что содержимое List
выбирается только при попытке получить к ним доступ. Например, вызывая course.getStudents().iterator()
. Вызов любого метода доступа в List
инициирует вызов базы данных для извлечения элементов. Это реализовано путем создания прокси-сервера вокруг List
(или Set
). Таким образом, для ваших ленивых коллекций конкретные типы не являются ArrayList
и HashSet
, но PersistentSet
и PersistentList
(или PersistentBag
)
Я могу рассмотреть производительность и использование памяти. Одно большое различие заключается в том, что страtagsя EAGER fetch позволяет использовать извлеченный объект данных без сеанса. Зачем?
Все данные извлекаются, когда требуются помеченные данные в объекте, когда сеанс подключен. Однако в случае ленивой страtagsи загрузки ленивая загрузка помеченного объекта не извлекает данные, если сеанс отключен (после оператора session.close()
). Все, что может быть сделано с помощью hibernate proxy. Стремительная страtagsя позволяет сохранять данные после закрытия сеанса.
По умолчанию для всех объектов коллекции и карты правило выборки – FetchType.LAZY
а для других экземпляров – политика FetchType.EAGER
.
@OneToMany
@ManyToMany
отношения @OneToMany
и @ManyToMany
не @ManyToMany
связанные объекты (сбор и карту) неявно, но операция поиска каскадируется через поле в @OneToOne
и @ManyToOne
.
(любезность: – objectdbcom)
По моим сведениям, оба типа выборки зависят от вашего требования.
FetchType.LAZY
по требованию (т.е. когда нам нужны данные).
FetchType.EAGER
является немедленным (т. FetchType.EAGER
До того, как наше требование приходит, мы без необходимости извлекаем запись)
Из Джавадока :
Страtagsя EAGER является обязательным требованием для среды выполнения поставщика непрерывности, которую данные должны получать с нетерпением. Страtagsя LAZY – это намек на время выполнения провайдера настойчивости, при котором данные должны извлекаться лениво при первом доступе.
Например, нетерпеливый более активен, чем ленив. «Ленивый» происходит только при первом использовании (если провайдер принимает подсказку), тогда как с нетерпеливыми вещами (может) получить предварительную выборку.
И FetchType.LAZY
и FetchType.EAGER
используются для определения плана выборки по умолчанию .
К сожалению, вы можете переопределить план выборки по умолчанию для получения LAZY. Выбор EAGER менее гибкий и может привести к многочисленным проблемам производительности .
Мой совет заключается в том, чтобы ограничить желание создавать ассоциации EAGER, потому что выборка – это ответственность за время запроса. Поэтому все ваши запросы должны использовать директиву fetch, чтобы получить только то, что необходимо для текущего бизнес-кейса.
Тип Lazy
Fetch по умолчанию выбран Hibernate, если вы явно не указали тип Eager
Fetch. Чтобы быть более точным и кратким, разница может быть указана ниже.
FetchType.LAZY
= Это не загружает отношения, если вы не вызываете его с помощью метода getter.
FetchType.EAGER
= Здесь загружаются все отношения.
Плюсы и минусы этих двух типов выборки.
Lazy initialization
повышает производительность, избегая ненужных вычислений и уменьшая требования к памяти.
Eager initialization
требует большего объема памяти, а скорость обработки медленная.
Сказав это, зависит от ситуации, которую может использовать одна из этих инициализаций.
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; @ManyToOne Subject 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 listBooks=new ArrayList (); public List getListBooks() { return listBooks; } public void setListBooks(List 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"); // configuration StandardServiceRegistryBuilder 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(); } } }
Проверьте метод retrieve () Main.java. Когда мы получим Subject, то его коллекция listBooks , аннотированная с @OneToMany
, будет загружена лениво. Но, с другой стороны, связанная с книгами ассоциация объекта коллекции, аннотированная с помощью @ManyToOne
, загружается с @ManyToOne
уклоном (по [default][1]
для @ManyToOne
, fetchType=EAGER
). Мы можем изменить поведение, поместив fetchType.EAGER в @OneToMany
Subject.java или fetchType.LAZY в @ManyToOne
в Books.java.
public enum FetchType extends java.lang.Enum Определяет страtagsи для извлечения данных из базы данных. Страtagsя EAGER является обязательным требованием для среды выполнения поставщика непрерывности, которую данные должны получать с нетерпением. Страtagsя LAZY – это намек на время выполнения провайдера настойчивости, при котором данные должны извлекаться лениво при первом доступе. Реализации разрешено охотно извлекать данные, для которых указана страtagsя LAZY. Пример: @Basic (fetch = LAZY) protected String getName () {return name; }
Источник
@ drop-shadow, если вы используете Hibernate, вы можете вызвать Hibernate.initialize()
когда вы вызываете метод getStudents()
:
Public class UniversityDaoImpl extends GenericDaoHibernate implements UniversityDao { //... @Override public 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; } //... }
LAZY: он извлекает дочерние объекты лениво, т. Е. Во время выборки родительского объекта он просто извлекает прокси (созданный cglib или любой другой утилитой) дочерних объектов и когда вы обращаетесь к любому свойству дочернего объекта, тогда он фактически извлекается с помощью спящего режима.
EAGER: он выбирает дочерние объекты вместе с родителем.
Для лучшего понимания обратитесь к документации Jboss или вы можете использовать hibernate.show_sql=true
для своего приложения и проверить запросы, выданные спящим режимом.