2012-04-25 5 views
14

Im пишет веб-приложение с использованием Hibernate 3.Лучшая практика работы с гибернатом?

Итак, через некоторое время я заметил, что что-то было медленным. Поэтому я протестировал hibernate-профайлер и обнаружил, что hibernate сделает неоправданно много вызовов db для простой работы. Причина в том, что я загружаю объект (у этого объекта есть несколько «родителей»), и у этих «родителей» есть другие «родители». Таким образом, базовый hibernate загружает их все, хотя мне нужен только базовый объект. Итак, я посмотрел на ленивую загрузку. Это привело меня к исключению Lazyloading, потому что у меня есть MVC webapp.

Итак, теперь я немного смущен относительно того, что является моим лучшим подходом к этому. В основном все, что мне нужно, это обновить одно поле объекта. У меня уже есть объектный ключ.

Должен ли я: 1. Копаться в ленивой загрузке. А затем переписать мое приложение для открытого сеанса? 2. Копайте в ленивую загрузку. А потом перепишите мои дао, чтобы быть более конкретными. Например. написание DAO-методов, которые возвратят объекты, созданные только для того, что необходимо для каждого случая использования? Может быть много дополнительных методов ... 3. Скрестить спящий режим и сделать это сам? 4. Не могу сейчас думать о других решениях. Какие-либо предложения?

Какая практика?

ответ

25
  • Не используйте соединения, если это действительно необходимо. Они не позволят вам использовать ни ленивую загрузку, ни использование кеша второго уровня для ассоциаций.
  • Используйте lazy = "extra" для больших коллекций, он не будет извлекать все элементы, пока вы не спросите об этом, вы также можете использовать размер(), например, без получения элементов из базы данных
  • Используйте метод load(), если это возможно, поскольку он не выдает запрос выбора до тех пор, пока он не понадобится. Например. если у вас есть книга и автор, и вы хотите, чтобы связать их вместе, это будет не выдает каких-либо выбирает, только одного вставки:

    Book b = (Book) session.load(Book.class, bookId); 
    Author a = (Author) session.load(Author.class, authorId); 
    b.setAuthor(a); 
    session.save(b); 
    
  • использовать именованные запросы (в ваших HBM файлов или в @NamedQuery), чтобы они не анализировались во время каждого запроса.Не используйте Criteria API, пока это не требуется (это делает невозможным использование кэш PreparedStatement в данном случае)

  • Используйте OSIV в вашем веб-приложение, так как она будет загружать данные только тогда, когда/если это необходимо
  • Используйте только для чтения режимов только для выборок: session.setReadOnly(object, true). Это приведет к тому, что Hibernate не будет сохранять исходный снимок выбранного объекта в постоянном контексте для дальнейших грязных проверок.
  • Пользовательский кэш второго уровня и кэш запросов для данных, предназначенных для чтения и чтения.
  • Используйте FlushMode.COMMIT вместо AUTO, чтобы Hibernate не выдавал выделение перед обновлениями, но будьте готовы, чтобы это могло привести к записи устаревших данных (хотя Optimistic Locking может помочь вам).
  • Посмотрите на пакетную выборку (размер партии), чтобы выбрать несколько сущностей/коллекций за один раз вместо того, чтобы выдавать отдельные запросы для каждого из них.
  • Выполнение таких запросов, как «выбрать новую Entity (id, someField) из Entity», чтобы получить только требуемые поля. Взгляните на трансформаторы результатов.
  • При необходимости используйте пакетные операции (например, удаление)
  • Если вы используете собственные запросы, укажите явно, какие области кеша должны быть недействительными (по умолчанию - все).
  • Взгляните на материализованный путь и вложенные множества для древовидных структур.
  • Установите c3p0.max_statements, чтобы включить кеш PreparedStatment в пул и включить кеш оператора в вашей БД, если он по умолчанию отключен.
  • Использование StatelessSession, если это возможно, он преодолевает грязные чеки, каскадирование, перехватчик и т.д.
  • Не используйте пагинацию (setMaxResults(), setFirstResult()) наряду с запросами, которые содержат присоединяются к коллекциям, это приведет все записи вытащили из база данных и разбиение на страницы будут происходить в памяти Hibernate. Если вам нужна разбивка на страницы, в идеале вы не должны использовать объединения. Если вы не можете избежать этого, снова - используйте пакетную выборку.

На самом деле есть много трюков, но я не могу больше вспомнить в данный момент.

+0

OSIV вы можете объяснить, что я не получил –

1

Я считаю, вы хотите просмотреть этот section in the Hibernate manual.

Я ожидаю, что ваша оригинальная проблема «... неоправданно много db-вызовов ...» является примером того, что они называют «проблема выбора N + 1». Если это так, у них есть варианты того, как с этим бороться.

  1. Сделать тип выборки Присоединиться. Тогда у вас будет один выбор с несколькими объединениями, если не будет промежуточных коллекций.
  2. Сделайте ленивую загрузку.
  3. Возможно, некоторые другие, например FetchProfiles, с которыми у меня нет опыта.

Первые два могут быть указаны на уровне ассоциации, а тип выборки может быть переопределен на уровне запроса. Вы должны иметь возможность получить свой запрос, чтобы сделать только то, что вам нужно, и больше, и сделать это с помощью «хорошего» SQL-запроса с помощью этих инструментов.

3

Как я объяснил в this article или мой High-Performance JavaPersistence book, есть много вещей, которые вы можете сделать, чтобы ускорить работу Hibernate, как:

  1. Enabling SQL statement logging, так что вы можете проверить все заявления и даже detect N+1 query problems during testing.
  2. управления Подключение к базе данных и мониторинг с помощью FlexyPool
  3. JDBC batching уменьшить количество необходимых туда и обратно, чтобы представить INSERT, UPDATE и DELETE заявление.
  4. JDBC Statement caching
  5. идентификатор JPA оптимизаторы как pooled or pooled-lo
  6. Выбор компактных типов столбцов
  7. Используйте правильные отношения: bidirectional @OneToMany instead of unidirectional one, используя @MapsId for @OneToOne, using Set for @ManyToMany
  8. Использование inheritance the right way и preferring SINGLE_TABLE for performance reasons
  9. Minding the Persistence Context size and avoiding long-running transactions
  10. Использование кэширования ОС , Кэширование БД до перехода к кэшу второго уровня whic ч полезно также разгрузить первичный узел при выполнении репликации баз данных
  11. раскрутить возможностей запросов к базе данных с помощью SQL native queries
  12. Split пишет среди нескольких один-к-одному субъектов к reduce optimistic locking false positives и получить больше шансов попасть в кэше базы данных даже при изменении определенных объектов.
Смежные вопросы