Вопрос по hibernate, performance, jpa, orm, java – Лучшая практика Hibernate Performance?

15

Я пишу веб-приложение, используя Hibernate 3.

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

Так что теперь я немного озадачен тем, каков мой лучший подход к этому. По сути, все, что мне нужно, это обновить одно поле на объекте. У меня уже есть объект-ключ.

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

Какова лучшая практика?

Ваш Ответ

3   ответа
1

раздел в руководстве по Hibernate.

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

Make the fetch type Join. Then you'll have a single select with several joins, assuming no intermediate collections. Do lazy loading. Probably some others, eg FetchProfiles which I've got no experience with.

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

4

Эта статья или мойВысокопроизводительная книга JavaPersistenceЕсть много вещей, которые вы можете сделать, чтобы ускорить производительность Hibernate, например:

Enabling SQL statement logging so that you can validate all statements and even detect N+1 query problems during testing. Database connection management and monitoring using FlexyPool JDBC batching to reduce the number of roundtrips needed to submit INSERT, UPDATE and DELETE statement. JDBC Statement caching JPA identifier optimizers like pooled or pooled-lo Choosing compact column types Use the right relationships: bidirectional @OneToMany instead of unidirectional one, using @MapsId for @OneToOne, using Set for @ManyToMany Using inheritance the right way and preferring SINGLE_TABLE for performance reasons Minding the Persistence Context size and avoiding long-running transactions Using OS caching, DB caching before jumping to 2nd-level cache which is also useful to off-load the Primary node when doing database replication Unleash database query capabilities via SQL native queries Split writes among multiple one-to-one entities to reduce optimistic locking false positives and get a better chance to hit the database cache even when modifying certain entities.
25
Don't use joins unless really needed. They won't allow you to use neither lazy loading, nor using 2nd level cache for associations Use lazy="extra" for large collections, it won't retrieve all the elements until you ask it, you can also use size() method for instance without getting elements from DB

s possible since it doesn't issue a select query until it's required. E.g. if you have a Book and an Author and you want to associate them together, this will won't issue any selects, only single insert:

Book b = (Book) session.load(Book.class, bookId);
Author a = (Author) session.load(Author.class, authorId);
b.setAuthor(a);
session.save(b);

Use named queries (in your hbm files or in @NamedQuery) so that they are not parsed during each query. Don't use Criteria API until it's required (it makes impossible to use PreparedStatement cache in this case)

Use OSIV in your web app since it will load data only when/if it's needed Use read-only modes for selects-only: session.setReadOnly(object, true). This will make Hibernate not to keep an original snapshot of the selected entity in the persistent context for further dirty checks. User 2nd level cache and Query Cache for read-mostly and read-only data. Use FlushMode.COMMIT instead of AUTO so that Hibernate doesn't issue select before updates, but be ready that this may lead to stale data being written (though Optimistic Locking can help you out). Take a look at batch fetching (batch-size) in order to select several entities/collections at one time instead of issuing separate queries for each one. Do queries like 'select new Entity(id, someField) from Entity' in order to retrieve only required fields. Take a look at result transformers. Use batch operations (like delete) if needed If you use native queries, specify explicitly what cache regions should be invalidated (by default - all). Take a look at materialized path and nested sets for tree-like structures. Set c3p0.max_statements in order to enable PreparedStatment cache in the pool and enable the statement cache of your DB if it's switched off by default. Use StatelessSession if it's possible, it overcomes dirty checks, cascading, interceptors, etc. Do not use pagination (setMaxResults(), setFirstResult()) along with queries that contain joins to collections, this will result in all the records pulled from database and pagination will happen in memory by Hibernate. If you want pagination, ideally you shouldn't use joins. If you can't escape it, again - use batch fetching.

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

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

Похожие вопросы