Документация Разработчика Hibernate — Глава Iv. Пакетная Обработка

Представляю вашему вниманию перевод четвертая глава официальной документации Hibernate .

Перевод статьи актуален для версии Hibernate 4.2.19.Final Следующая глава Документация разработчика Hibernate — Глава V. Блокировки Содержание &nbsp 4.1. Пакетные вставки &nbsp 4.2. Пакетные обновления &nbsp 4.3. Сеанс без гражданства &nbsp 4.4. Язык запросов Hibernate для DML &nbsp&nbsp&nbsp 4.4.1. HQL для ОБНОВЛЕНИЯ и УДАЛЕНИЯ &nbsp&nbsp&nbsp 4.4.2. Синтаксис HQL для INSERT Следующий пример демонстрирует антишаблон пакетной вставки.

Пример 4.1. Наивный способ вставить 100000 строк с помощью Hibernate

  
  
  
  
  
  
  
  
  
   

Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); for ( int i=0; i<100000; i++ ) { Customer customer = new Customer(.

); session.save(customer); } tx.commit(); session.close();

Этот код вызовет исключение Исключение OutOfMemoryException после обработки около 50 000 строк в большинстве систем.

Причина в том, что Hibernate кэширует все вновь созданные экземпляры.

Клиент в кеше уровня сеанса.

Есть несколько способов избежать этой проблемы.

Прежде чем начать работу с пакетной обработкой, включите ее в JDBC. Чтобы включить пакетную обработку, введите в свойстве значение от 10 до 50. hibernate.jdbc.batch_size .

Важный Hibernate прозрачно отключает пакетные вставки на уровне JDBC, если вы используете генератор идентификаторов.

Если такой подход неприемлем, вы можете отключить кеш второго уровня, установив свойство hibernate.cache.use_ Second_level_cache В ЛОЖЬ

4.1. Пакетные вставки

Когда вы делаете новые объекты постоянными, используйте методы сеанса.

румянец() И прозрачный() для управления размером кэша первого уровня.

Пример 4.2. Сеанс промывки и очистки

Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); for ( int i=0; i<100000; i++ ) { Customer customer = new Customer(.

); session.save(customer); if ( i % 20 == 0 ) { //20, same as the JDBC batch size //flush a batch of inserts and release memory: session.flush(); session.clear(); } } tx.commit(); session.close();



4.2. Пакетные обновления

Используйте регулярно румянец() И прозрачный() когда вы извлекаете и изменяете данные.

Кроме того, используйте метод прокрутка() чтобы получить преимущества работы с курсорами базы данных для запросов, возвращающих большое количество строк.

Пример 4.3. Применение прокрутка()

Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); ScrollableResults customers = session.getNamedQuery("GetCustomers") .

setCacheMode(CacheMode.IGNORE) .

scroll(ScrollMode.FORWARD_ONLY); int count=0; while ( customers.next() ) { Customer customer = (Customer) customers.get(0); customer.updateStuff(.

); if ( ++count % 20 == 0 ) { //flush a batch of updates and release memory: session.flush(); session.clear(); } } tx.commit(); session.close()



4.3. Сеанс без гражданства

Сеанс без гражданства — это командно-ориентированный API, предоставляемый Hibernate. Используйте его для потоковой передачи данных в базу данных и из нее в виде отдельных объектов.

Сеанс без гражданства не имеет связанного контекста персистентности и не обеспечивает большую часть семантики высокого уровня.

Функции, не предоставляемые StatelessSession: Кэш 1 уровня Взаимодействие с кешем первого уровня или кешем запросов Транзакционный отложенная запись или автоматическая проверка модификаций ( грязная проверка ) Ограничения StatelessSession: Операции, выполняемые StatelessSession, не передаются каскадно связанным объектам.

Коллекции игнорируются Операции, выполняемые через StatelessSession, обходят модель событий Hibernate и ее перехватчики.

Из-за отсутствия кэша первого уровня StatelessSessions уязвимы к воздействию нескольких псевдонимов данных ( эффект совмещения данных с).

StatelessSession — это низкоуровневая абстракция, более близкая к базовому JDBC. Пример 4.4. Использование StatelessSession

StatelessSession session = sessionFactory.openStatelessSession(); Transaction tx = session.beginTransaction(); ScrollableResults customers = session.getNamedQuery("GetCustomers") .

scroll(ScrollMode.FORWARD_ONLY); while ( customers.next() ) { Customer customer = (Customer) customers.get(0); customer.updateStuff(.

); session.update(customer); } tx.commit(); session.close();

Объекты Клиент , возвращенный запросом, будет немедленно отсоединен.

Они не будут связаны ни с каким контекстом персистентности.

Операции вставлять() , обновлять() , И удалить() определено в интерфейсе Сеанс без гражданства работать напрямую со строками таблицы.

Они приводят к немедленному выполнению соответствующих SQL-операций, поскольку имеют иную семантику, чем методы.

сохранять() , сохранитьилиобновить() , И удалить() , определенный в интерфейсе сеанса.



4.4. Язык запросов Hibernate для DML

ДМЛ или Язык разметки данных относится к операторам SQL, таким как INSERT, UPDATE и DELETE. Hibernate предоставляет методы для пакетного выполнения SQL-подобных операций DML в форме HQL( Язык запросов Hibernate ).



4.4.1 HQL для ОБНОВЛЕНИЯ и УДАЛЕНИЯ

Пример 4.5. Псевдосинтаксис для выражений UPDATE и DELETE с использованием HQL

( UPDATE | DELETE ) FROM? EntityName (WHERE where_conditions)?

Суффикс? означает необязательный параметр.

FROM и WHERE являются необязательными.

FROM может указывать только на одну сущность, которая может иметь псевдоним.

Если имя сущности имеет псевдоним, все ссылки на свойства должны уточняться этим псевдонимом.

Если имя сущности не имеет псевдонима, ссылки не должны уточняться.

Объединения, явные или неявные, запрещены в групповых запросах HQL. Вы можете использовать подзапросы в предложении WHERE, а сами подзапросы могут содержать соединения.

Пример 4.6. Выполнение HQL UPDATE с помощью метода Query.executeUpdate()

Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); String hqlUpdate = "update Customer c set c.name = :newName where c.name = :oldName"; // or String hqlUpdate = "update Customer set name = :newName where name = :oldName"; int updatedEntities = session.createQuery( hqlUpdate ) .

setString( "newName", newName ) .

setString( "oldName", oldName ) .

executeUpdate(); tx.commit(); session.close();

Согласно спецификации EJB3, операторы HQL UPDATE по умолчанию не влияют на версию или значения временных меток измененных сущностей.

Вы можете использовать обновление управления версиями, чтобы заставить Hibernate сбросить версию или метку времени, добавив ключевое слово VERSIONED после UPDATE. Пример 4.7. Обновить версию временной метки

Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); String hqlVersionedUpdate = "update versioned Customer set name = :newName where name = :oldName"; int updatedEntities = session.createQuery( hqlUpdate ) .

setString( "newName", newName ) .

setString( "oldName", oldName ) .

executeUpdate(); tx.commit(); session.close();

Важный Если вы используете выражение VERSIONED, вы не можете использовать пользовательские типы версий, использующие класс org.hibernate.usertype.UserVersionType Пример 4.8. HQL-выражение УДАЛИТЬ

Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); String hqlDelete = "delete Customer c where c.name = :oldName"; // or String hqlDelete = "delete Customer where name = :oldName"; int deletedEntities = session.createQuery( hqlDelete ) .

setString( "oldName", oldName ) .

executeUpdate(); tx.commit(); session.close();

Метод Запрос.

executeUpdate() возвращает значение типа интервал , который показывает количество объектов, затронутых операцией.

Это число не обязательно должно коррелировать с количеством строк, обновляемых в базе данных.

Групповая операция в HQL может состоять из нескольких выражений SQL, например для объединенного подкласса (joined-subclass).

В примере подкласса объединения DELETE для одного из подклассов может фактически привести к удалению в таблицах ниже объединения или ниже в иерархии наследования.



4.4.2 Синтаксис HQL для INSERT

Пример 4.9. Псевдосинтаксис для операторов INSERT

INSERT INTO EntityName properties_list select_statement

Поддерживается только форма INSERT INTO. SELECT. Вы не можете указать явные значения для вставки.

список_свойств это аналогично указанию столбцов в инструкции SQL INSERT. Для сущностей, участвующих в сопоставлении наследования ( сопоставленное наследование ), вы можете указать свойства, указанные непосредственно в самом классе, но не в подклассах или родительском классе.

Другими словами, выражение INSERT не является полиморфным по своей сути.

select_statement может быть любым допустимым запросом выбора HQL, но типы возвращаемых данных должны соответствовать типам, ожидаемым в INSERT. Hibernate проверяет возвращаемые типы во время компиляции, а не ждет, пока СУБД проверит их.

Проблемы могут возникнуть из-за типов Hibernate, которые скорее эквивалентны, но не равны.

Одним из примеров этого является несоответствие между свойством, определенным как org.hibernate.type.DateType, и свойством, определенным как org.hibernate.type.TimestampType, даже если база данных не различает их или способна выполнять преобразование типов.

сам.

Если имущество идентификатор не указано в список_свойств , Hibernate генерирует значение автоматически.

Автоматическая генерация доступна только в том случае, если вы используете генераторы идентификаторов.

В противном случае Hibernate выдаст исключение во время анализа.

Генераторы, доступные для баз данных: org.hibernate.id.SequenceGenerator и его подклассы, а также объекты, реализующие org.hibernate.id.PostInsertIdentifierGenerator .

Наиболее заметным исключением является org.hibernate.id.TableHiLoGenerator , который не предоставляет никакого способа получить его значения.

Для свойств, проецируемых как версия или временная метка, оператор вставки предоставляет два варианта.

Вы можете либо указать свойство в список_свойств , в этом случае значение будет взято из сопровождающего выражения выбора или удалено из список_свойств , и в этом случае начальное значение, определенное в org.hibernate.type.VersionType .

Пример 4.10. HQL-выражение INSERT

Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); String hqlInsert = "insert into DelinquentAccount (id, name) select c.id, c.name from Customer c where .

"; int createdEntities = session.createQuery( hqlInsert ) .

executeUpdate(); tx.commit(); session.close();

Теги: #hibernate #java #orm #документация #java

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.