В этой статье описывается технология загрузки задержки с гибернат. Поделитесь этим для вашей ссылки, следующим образом:
Ленивая загрузка Hibernae - очень распространенная техника. Сборные атрибуты объектов будут отложены по умолчанию, а объекты, связанные с объектами, также будут отложены по умолчанию. Hibernate использует эту отсроченную нагрузку, чтобы уменьшить накладные расходы системы, обеспечивая тем самым рабочие характеристики Hibernate.
Давайте сначала проанализируем «секрет» загрузки задержки сгибания.
Ленивая загрузка свойств сбора
Когда Hibernate инициализирует постоянную сущность из базы данных, инициализируется ли атрибут сбора этой сущности с постоянным классом? Если атрибут сбора содержит 100 000 или даже миллионы записей, ползание всех атрибутов коллекции при инициализации постоянной сущности приведет к резкому снижению производительности. Вполне возможно, что система должна использовать только некоторые записи в атрибутах коллекции постоянного класса, а не все атрибуты коллекции вообще. Таким образом, нет необходимости загружать все атрибуты сбора одновременно.
Ленивые стратегии загрузки обычно рекомендуются для сбора свойств. Так называемая отсроченная загрузка заключается в загрузке связанных данных из базы данных, когда система должна использовать атрибуты сбора.
Например, следующий класс человека содержит атрибут коллекции, а элемент в атрибуте коллекции имеет адрес типа, а фрагмент кода класса человека заключается в следующем:
Список 1. Person.java
Public Class Person {// определить атрибут частного целочисленного идентификатора; // атрибут имени человека частное имя строки; // сохранить возраст человека в частном возрасте; // Использование SET для сохранения атрибута коллекции Private SET <Adder> Addedes = New Hashset <drade> (); // Методы сеттера и получения каждого атрибута опущены ниже ...}Чтобы Hibernate управлял свойствами сбора постоянного класса, программа предоставляет следующие файлы отображения для постоянного класса:
Листинг 2. Person.hbm.xml
<? xml version = "1.0" Encoding = "gbk"?> <! Doctype hibernate mapping public "-// hibernate/hibernate mapping dtd 3.0 // en" "http://www.hibernate.org/dtd/hibernate-paping-3.0. package = "org.crazyit.app.domain"> <!-класс Persistence Persion Person Persons-> <class name = "person" table = "person_inf"> <!-идентификатор идентификации идентификации отображения-> <id name = "id" = "person_id"> <!-определить политику первичного генератора ключе name = "age" type = "int"/> <!-атрибуты коллекции карт-> <set name = "address" table = "person_address" lazy = "true"> <!-Укажите связанный столбец иностранного ключа-> <ключевой столбец = "person_id"/> <composite-lelement> <!-Материал нормальный атрибут-> <propation = "detail"/> <! name = "Zip"/> </composite-lelement> </set> </class> </hibernate-mapping>
Из приведенного выше кода, который отображает файл, мы видим, что атрибут класса адреса лично лично является просто обычным Pojo. Адрес класса содержит два атрибута: детали и Zip. Поскольку код класса адреса очень прост, код для этого класса больше не дан здесь.
Код в элементе <set .../> в приведенном выше файле сопоставления указывает lazy = "true" (для <set .../> element, lazy = "true" - это значение по умолчанию), в котором указано, что Hibernate будет откладывать загрузку объекта адреса в атрибуте коллекции.
Например, загрузите объект человека с идентификатором 1, следуя следующему коду:
Session Session = sf.getCurrentSession (); Transaction tx = session.beginTransaction (); человек p = (человек) session.get (person.class, 1); // <1> System.out.println (p.getName ());
Приведенный выше код просто должен получить доступ к личному объекту с идентификатором 1 и не хочет получить доступ к объекту адреса, связанного с этим лицом. В настоящее время есть две ситуации:
1. Если загрузка не задерживается, Hibernate немедленно захватит адресный объект, связанный с объектом лица при загрузке записи данных, соответствующей объекту лица.
2. Если используется ленивая загрузка, Hibernate будет загружать только записи данных, соответствующие объекту лица.
Очевидно, что второй подход не только снижает взаимодействие с базой данных, но и избегает накладных расходов на память, вызванные объектами загрузки адресов, - именно поэтому Hibernate позволяет ленировать загружать по умолчанию.
Теперь вопрос в том, как реализована ленивая загрузка? Hibernate Каковы адреса стоимости собственности личности при загрузке лица?
Чтобы решить эту проблему, мы установили точку останова в коде <1> и отлаживают ее в Eclipse. В настоящее время мы видим, что окно консоли Eclipse имеет выход, как показано на рисунке 1:
Рисунок 1. Выход консоли для ленивых свойств сбора нагрузки
Как показано на выходе на рисунке 1, Hibernate захватывает данные только из таблицы данных, соответствующей объекту лица, и не получает данные из таблицы данных, соответствующей объекту адреса. Это ленивая загрузка.
Итак, каковы адреса собственности лица личности? В настоящее время вы можете увидеть результаты, показанные на рисунке 2 из окна переменных Eclipse:
Рисунок 2. Ленитые значения атрибутов сбора нагрузки
Из контента на коробке на рисунке 2 можно увидеть, что свойство адресов не представляет собой не знакомые классы реализации, такие как Hashset и Treesset, а класс реализации PersistentSet, который является классом реализации, предоставленным Hibernate для установленного интерфейса.
Объект сбора PersistentSet на самом деле не собирает данные базовой таблицы данных, поэтому, естественно, невозможно по -прежнему инициализировать объект адреса в сборе. Тем не менее, коллекция PersistentSet содержит атрибут сессии, который является сеансом Hibernate. Когда программа необходимо получить доступ к элементу сбора PersistentSet, PersistentSet будет использовать этот атрибут этого сеанса, чтобы получить записи данных, соответствующие фактическому объекту адреса.
Итак, что именно вы получаете записи данных, соответствующие этим адресам адреса? Это не сложно для Persistentset, потому что в коллекции PersistentSet есть также атрибут владельца, что указывает на объект личности, к которому принадлежит объект адреса. Hibernate будет искать данные из таблицы данных, соответствующих адресу, соответствующему таблице данных.
Например, мы нажимаем на строку адресов в окне, показанном на рисунке 2, что означает, что мы говорим Eclipse отладки и выводу атрибута адресов. Это для доступа к атрибуту адресов. В настоящее время вы можете увидеть следующие операторы SQL в окне консоли Eclipse:
Выберите AdderseS0_.Person_ID AS Person1_0_0_, Adders0_.detail AS AS DELATION0_, ADDRESS0_.ZIP AS ZIP0_FROM Person_Address Addedes0_where Addedes0_.person_id =?
Это операторы CollectionSet и SQL, которые фиксируют конкретные адресные записи в соответствии с атрибутом владельца. В настоящее время вы можете увидеть выход, показанный на рисунке 3 из окна переменных Eclipse:
Рисунок 3. Загруженные значения атрибутов сбора
Как видно из рисунка 3, атрибут адресов в настоящее время был инициализирован, и набор содержит 2 объекта адреса, которые являются двумя объектами адреса, связанными с объектом человека.
Из приведенного выше введения мы видим, что ключ для задержки загрузки набора атрибутов Hibernate заключается в классе реализации PersistentSet. Во время ленивой загрузки коллекция PersistentSet не содержит никаких элементов. Тем не менее, Persistentset проведет сеанс Hibernate, который может гарантировать, что когда программа необходимо получить доступ к сбору, запись данных загружается «немедленно» и загрузить элементы сбора.
Подобно классу внедрения PersistentSet, Hibernate также предоставляет Persistentlist, PersistentMap, PersistentSortedMap, PersistentEntsortedSet и другие классы реализации, а их функции примерно аналогичны функциям PersistentEntset.
Читатели, которые знакомы с атрибутами коллекции Hibernate, должны помнить: Hibernate требует, чтобы атрибуты Declare Collection могут использоваться только с такими интерфейсами, как SET, List, Map, SortedSet, SortedMap и т. Д., И не могут быть реализованы с использованием Hashset, Arraylist, Hashmap, Treesset, Treemap и других классов реализации. The reason is that Hibernate needs to delay loading the collection attributes, and the delay loading of Hibernate relies on PersistentSet, PersistentList, PersistentMap, PersistentSortedMap, and PersistentSortedSet to complete - that is, the underlying Hibernate needs to use its own collection implementation class to complete the lazy loading, so it requires developers to use the collection interface, rather than the collection implementation class to declare collection атрибуты.
Hibernate использует ленивую загрузку для атрибутов сбора по умолчанию. В некоторых особых случаях установите атрибут lazy = "false" для таких элементов, как <set .../>, <list .../>, <map .../>, чтобы отменить ленивую загрузку.
Задержка загрузки ассоциированных объектов
По умолчанию Hibernate также будет использовать ленивую нагрузку для загрузки связанной сущности. Будь то ассоциация «один ко многим», ассоциация один на один или ассоциация многих ко многим, Hibernate будет использовать ленивую нагрузку по умолчанию.
Для ассоциированных сущностей они могут быть разделены на два случая:
1. Когда связанная сущность-это несколько сущностей (в том числе один-один, многие-многие): в настоящее время связанная организация будет существовать в форме сбора, а Hibernate будет использовать Persistentset, PersistentList, PersistentMap, PersistentEdEdMap, PersistentEntestedSet и другие коллекции для управления Laze Buiting Entries. Это ситуация, представленная ранее.
2. Когда связанная сущность является единственной сущностью (включая один к одному и многим к одному): когда Hibernate загружает сущность, задержка связана сопутствующая сущность будет динамически сгенерированным прокси-объектом.
Когда ассоциированная сущность является единственной сущностью, то есть, когда связанная сущность отображается с использованием <много-один .../> или <один к одному .../>, эти два элемента также могут указывать ленивую нагрузку через ленивый атрибут.
Следующий пример также отображает класс адреса на постоянный класс. В настоящее время класс адреса также становится классом сущностей, а объект личности и адреса Addrest образуют двустороннюю двустороннюю ассоциацию. Код файла отображения в настоящее время выглядит следующим образом:
Листинг 3. Person.hbm.xml
<? xml version = "1.0" Encoding = "GBK"?> <!-Укажите информацию DTD для Hibernate-> <! Doctype Hibernate Mapping Public "-// Hibernate/Hibernate Mapping DTD 3.0 // en "" http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd "> <hibernate moppation package =" org.crazyit.app.domain "> <!-класс Persipport Persontence Persiping Persipence-> <class name = table =" Person_Inf "> <!-MAPPAPING Persipport. Column = "Person_ID"> <!-определить политику генератора первичных ключей-> <Generator/> <!-используется для карты общих атрибутов-> <name = "name" type = "string"/> <name = "age" type = "int"/> <!-Атрибуты сбора карт, элемент сбора-это еще одна постоянная целесообразно upverse = "true"> <!-Укажите связанный столбец иностранного ключа-> <ключ Column = "person_id"/> <!-используется для карты атрибутов ассоциированного класса-> <One-to-many/> </set> </class> <!-Карта. Укажите политику генератора первичных ключей-> <generator/> </id> <!-MAP нормальный атрибут детали атрибута-> <name = "detail"/> <!-карта нормальный атрибут Zip-> <name = "Zip"/> <!-Имя столбца должно быть указано как Person_id, что такое же, как и значение столбца колонки, в соответствующем элементе-> <много-по-имя = "Person_Id" = "storm_id '". not null = "true"/> </class> </hibernate-mapping>
Далее, программа загружает объект человека с идентификатором 1 через следующий фрагмент кода:
// Откройте контекстно-зависимую сеанс сеансессии = sf.getCurrentSession (); Transaction tx = session.beginTransaction (); Addch Address = (адрес) session.get (address.class, 1); // <1> System.out.println (address.getDetail ());
Чтобы увидеть обработку связанной объекта Hibernate при загрузке адреса адреса, мы устанавливаем точку останова в коде <1> и отлаживают ее в Eclipse. В настоящее время мы видим, что окно консоли Eclipse выводит следующее оператор SQL:
выберите Address0_.address_id AS ADDRES1_1_0_, ADDRES0_.DETAIL AS DETAIL1_0_, ADDRES0_.ZIP AS ZIP1_0_, ADDRESS0_.PERSON_ID AS Person4_1_0_ из ADDRICE_INF ADDRESS0_WHEWARD ADDRESS0_.Address_ID =?
Из этого оператора SQL не сложно увидеть, что Hibernate загружает таблицу данных, соответствующую объекту адреса, для заполнения записей, но не заполняет записи из таблицы данных, соответствующей личному сущности, которая заключается в том, что ленивая нагрузка играет роль.
В окне переменных затмения см. Вывод, показанный на рисунке 4:
Рисунок 4. Задержка нагрузочной сущности
Из рисунка 4 можно ясно видеть, что сущность человека, связанная с объектом адреса, является не человеком, а экземпляр человека _ $$ _ javassist_0. Этот класс является прокси -классом, динамически сгенерированным Hibernate с использованием Javassist Project. Когда Hibernate задерживает загрузку связанного объекта, Javassist будет использоваться для генерации динамического прокси -объекта, и этот объект прокси будет отвечать за прокси «еще не загружен».
Пока приложение должно использовать связанную сущность, которая «еще не загружена», объект прокси -сервера Javassist_0 Javassist_0 будет нести ответственность за загрузку реальной ассоциированной сущности и возврат фактического связанного объекта - это наиболее типичный прокси -шаблон.
Щелкните атрибут человека в окне переменных, показанном на рисунке 4 (то есть заставите атрибут человека использовать в режиме отладки), а затем вы увидите следующие операторы SQL, выводящие в окне консоли Eclipse:
Выберите Person0_.person_id As Person1_0_0_, Person0_.name As name0_0_, Person0_.age As Age0_0_ из Person_inf Person0_where person0_.person_id =?
Приведенный выше оператор SQL является утверждением, которое фиксирует связанную сущность «задержки загрузки». В настоящее время вы можете увидеть результаты, показанные на рисунке 5 вывода окна переменных:
Рисунок 5. Загруженная сущность
Hibernate принимает режим «отсроченной нагрузки» для управления ассоциированными объектами. Фактически, при загрузке основной сущности она на самом деле не получает соответствующие данные ассоциированной сущности, но просто динамически генерирует объект в качестве прокси -сервера ассоциированной сущности. Когда приложение действительно необходимо использовать связанную сущность, объект прокси отвечает за захват записей из базовой базы данных и инициализации реальной связанной сущности.
В сбросе задержки задержка, то, что начинает получать клиентскую программу, является динамически сгенерированным прокси -объектом, в то время как реальная сущность делегируется в объект Proxy для управления - это типичный прокси -шаблон.
Режим агента
Прокси -режим - это режим проектирования с очень широким применением. Когда клиент -код должен вызвать объект, клиенту на самом деле не волнует, следует ли точно получить объект. Ему нужен только объект, который может обеспечить функцию. В настоящее время мы можем вернуть прокси (прокси) объекта.
В этом методе проектирования система предоставит объект с прокси -объектом, а объект прокси управляет ссылкой на исходный объект. Прокси - это объект Java, который действует от имени другого объекта Java. В некоторых случаях клиент -код не хочет или не может напрямую вызовать Callee, а объект прокси может действовать как посредник между клиентом и целевым объектом.
Для клиентов это не может различить разницу между прокси -объектом и реальным объектом, а также не нужно различать разницу между прокси -объектом и реальным объектом. Клиентский код не знает реального объекта прокси. Клиентский код ориентирован на интерфейс и содержит только интерфейс объекта прокси.
Короче говоря, до тех пор, пока клиент -код не может или не хочет непосредственно получить непосредственный доступ к вызываемому объекту - существует много причин для этой ситуации, например, создание объекта с высокими накладными расходом системы, или вызываемый объект находится на удаленном хосте, или функции целевого объекта недостаточно для удовлетворения потребностей ..., но дополнительный прокси -объект создается, чтобы вернуть его клиенту для использования, так что этот метод проектирования является режим Proxy.
Следующее демонстрирует простой прокси -режим. Сначала программа предоставляет интерфейс изображения, представляющий интерфейс, реализованный большим объектом изображения. Код интерфейса заключается в следующем:
Листинг 3. Image.java
public interface image {void show ();}Этот интерфейс предоставляет класс реализации, который имитирует большой объект изображения, а конструктор класса реализации использует метод Thread.sleep () для паузы 3S. Ниже приведен программный код для облигации.
Список 4. Bigimage.java
// Использование этого облигации для моделирования большого изображения открытый класс. System.out.println ("Успешная загрузка изображения ...");} Catch (прерывание EX) {ex.printStackTrace ();}} // Реализуйте метод Show () в изображении public void show () {System.out.println ("Нарисуйте фактическую большую картину");}}}}}}}}}}}}}}}}}}}}}}}}}}}Приведенный выше код программы приостанавливает 3S, что указывает на то, что для создания объекта Bigimage объект занимает 3S - программа использует эту задержку для моделирования накладных расходов системы, вызванной загрузкой этого изображения. Если прокси -режим не используется, система будет генерировать задержку 3S, когда в программе создается бигмимаж. Чтобы избежать этой задержки, программа предоставляет прокси -объект для объекта Bigimage, а класс прокси в классе Bagimage заключается в следующем.
Список 5. ImageProxy.java
открытый класс ImageProxy реализует Image {// Объединение экземпляра изображения в качестве Proxy Object Private Image Image; // Использование абстрактных сущностей для инициализации Proxy Object Public ImageProxy (изображение изображения) {this.image = image;}/*** Переписать метод Show () интерфейса изображения* используется для управления доступа к объекту Proxy, и отвечает за создание и Deltet, чтобы создать и DELTET ONSOMY VOLESY VOLISY PUPRODES PUPLECTY PUPLESY. show () {// Создать только объект прокси только if (image == null) {image = new Bagimage ();} image.show ();}}Приведенный выше класс Proxy ImageProxy реализует тот же метод Show (), что и Bigimage, который позволяет клиентскому коду использовать объект прокси в качестве облигации после получения прокси -объекта.
Логика управления добавляется в метод Show () класса ImageProxy. Эта логика управления используется для управления тем, что объект Bugimage Proxy будет создан только тогда, когда система фактически вызывает Show () изображения. Следующая программа должна использовать объект Bigimage, но программа не возвращает экземпляр Bigimage, но сначала возвращает объект Proxy Bigimage, как показано в следующей программе.
Список 6. bigimagetest.java
Общедоступный класс Bigimagetest {public static void main (string [] args) {long start = System.currentTimeMillis (); // Программа возвращает объект изображения, который является лишь прокси -объектом Image Image = New ImageProxy (null); System.out.println («Time Overhedhed of System, получающая объект Image:» +(System.currentItITIM () Программа фактически создаст прокси -объект, когда на самом деле будет вызван метод Show () прокси изображения. image.show ();}}Приведенная выше программа очень быстро инициализирует изображение, потому что программа на самом деле не создает объект Bigimage, а просто получает объект Proxy ImageProxy - до тех пор, пока программа не вызовет метод Image.show (), программа должна фактически вызвать метод Show () объекта Bigimage, а программа действительно создает объект Bigimage в настоящее время. Запустите вышеуказанную программу и посмотрите результаты, показанные на рисунке 6.
Рисунок 6. Повышение производительности с использованием прокси -режима
Видя выполняемые результаты, показанные на рисунке 6, читатели должны быть в состоянии согласиться с тем, что использование прокси -режима улучшает производительность системы получения объектов изображения. Но некоторые читатели могут задать вопросы: когда программа вызывает метод Show () объекта ImageProxy, она также должна создать объект Bigimage, но накладные расходы системы не были действительно уменьшены? Просто эта система задерживается?
Мы можем ответить на этот вопрос с следующих двух точек зрения:
Задержка создания облигации до тех пор, пока оно не будет необходимым, может обеспечить плавную работу предыдущей программы и сократить время выживания в памяти, сохраняя накладные расходы системы с точки зрения макро.
В некоторых случаях, возможно, программа никогда не будет называть метод Show () объекта ImageProxy, что означает, что система вообще не нужно создавать объект Bigimage вообще. В этом случае использование прокси -режима может значительно улучшить производительность работы системы.
Подобно схоже, Hibernate также использует прокси -режим, чтобы «задержать» время для загрузки связанной сущности. Если программе не нуждается в доступе к связанной организации, программа не будет ползти связанной организации. Это может сохранить накладные расходы системы и сократить время, когда Hibernate загружает сущность.
краткое содержание
Lazy Lazy Lazy Lazy Lazy Lazy - это применение режима прокси. В последние годы мы часто использовали прокси -режим для сокращения накладных расходов на системную память и повысить производительность приложения. Hibernate использует это преимущество режима прокси и объединяет Javassist или Cglib для динамического генерации прокси -объектов, что добавляет гибкость в режим прокси. Hibernate дает этому использованию новое имя: ленивая загрузка. В любом случае, полностью анализ и понимание реализации этих рамках с открытым исходным кодом может лучше испытать преимущества классических моделей дизайна.
Я надеюсь, что описание в этой статье будет полезно для каждого Java -программирования на основе пластинга Hibernate.