Why Is Hibernate Open Session in View Considered a Bad Practice

Is it a good idea to open a hibernate session in controller in MVC architecture?

Session in view is a bad practice.

Here is a suggestion for layers which are typically used to work around this problem:

Controller

  • The controller is only concerned with handling web requests, interpreting them into objects that your services will deal with, and returning services results as web responses. I usually have only one transactional service method call in each controller method, preferring to keep all data access for one controller operation within a single transaction.

Service

  • The service layer is only concerned with accepting data from controller, obtaining the data it needs (from data layer) to perform its operations, and returning meaningful results. The service should fully load all lazy-loaded entities required by the controller. The service methods here are transactional and won't have lazy loading issues, and you can assemble results from multiple DAO's. That way DAO's don't need to know about each other.

Data Access

  • The data access layer is only concerned with persistence (CRUD), allowing access to data with filtering, ordering, and so on.

hibernate Open Session in View

could you explain why do you need to have ur transactions in ur repositories? the problem there is that they are going to be so fine-grained, so you are not gonna get any advantage from the session caching

then you are opening the transaction there but closing it in your filter. what happens if you access multiple repositories in your service? Maybe i am not understanding what you mean but i think you need to re-think the reasons that force you to manage your transactions in your repositories

Avoid hibernate session destruction between methods

There's the session per request pattern. Have a look here for a description. If you're using spring there's a filter implementation for this.

Be aware that its use is contoversial: Why is Hibernate Open Session in View considered a bad practice?

When do we need to .save() an entity in Spring?

Conclusion

It depends on whether the method is contained in a transaction or not.

  • In a transaction: the above code works as expected implicitly.
  • Not in a transaction: the .save() must be called explicitly to update the database.

How can I detect cases like these and know exactly when to use the .save() method and when can I ignore it?

  • The .save() method must be called for a modified entity explicitly if:

    1. The changing code does not belong to a transaction.
    2. The entity is newly created: new Car().
    3. The entity object is obtained externally, not from the database within the same transaction. (E.g. already saved in a List before the transaction begins.)
  • The .save() method does not have to be called for entities which are queried from JPA within the same transaction. (E.g. carRepository.findById(id) and other similar methods).

Transaction

If the above sequence of events is called from a method annotated by @Transactional, then it would work as expected.

Then the created Car object becomes managed by the persistence context and all changes to it, within the same transaction, are flushed after the transaction is completed.

No Transaction

If the above method does not belong to any transaction, all changes to the objects are local (object properties change, but are not flushed to database).

That is why calling persist() or merge() (in the above case, save() which internally uses those two) must be done explicitly to flush the changes.

Better to Use Transactions

Saving a single entity executes a single SQL query, which is atomic, thus a transaction itself. If the sequence of database events is not contained in a transaction, then each save() call acts as a standalone "transaction".

Usually, this is bad practice, because if one of the later "transactions" fail (some kind of Exception thrown), the previous succeeded transactions have already been flushed, possibly bringing the database to an invalid state from the business logic perspective.


Open Session In View

The behavior has nothing to do with OSIV.

OSIV keeps the database session open during view rendering, so that further queries (transactions) could be performed after the main request processing has finished, in the view layer. Using OSIV is widely considered an anti-pattern.

  • Why is Hibernate Open Session In View considered a bad practice?
  • JPA @Entity not managed after creation?

Open Session in view for new version of Hibernate

Take a look at the ThreadLocalSessionContext and ManagedSessionContext classes. It should help you do what you need.

If you look at spring's implementation of the filter, it will most likely be using the ThreadLocalSessionContext class.

What is this spring.jpa.open-in-view=true property in Spring Boot?

This property will register an OpenEntityManagerInViewInterceptor, which registers an EntityManager to the current thread, so you will have the same EntityManager until the web request is finished. It has nothing to do with a Hibernate SessionFactory etc.



Related Topics



Leave a reply



Submit