简体   繁体   中英

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

I have a pretty complex domain entities. I want to have lazy loading for all of associations. So the scenario is like this:

1.get an instance of my business logic.

2.get an object o from business.

3.ask o to give me other associated objects.

4.prepare the view.

To get rid of hibernate exceptions about closed session when lazy load other objects, I've come up to the idea to open and close entire session in controller. Is it a good idea? Are there any better solutions?

Thank you

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.

Spring有一个opensessioninviewfilter和一个opensessininviewinterceptor ,它们应该为您处理此功能。

As a design pattern openinig session in view is very bad. I think that SpringMVC has a setting that causes opening session for you and solves your problem.

However I'd suggest not using this pattern if your application is more complex than a pet store. I'd suggest moving data retrieval and business logic one layer down and leave only UI-related code in controllers. Tethinking relations and setting eager and lazy settings on them should work. Setting everything to lazy without analysis is not a good idea. It'll end up in hundreds of SQL calls per request.

I'd suggest plugging L2 cache (eg EHCache) to Hibernate. Configuration and usage is really easy.

You can indeed do it and it is a common pattern when using Spring and Hibernate. You can enable it very easily by putting the code below in your web.xml

<filter>
    <filter-name>lazyLoadingFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>lazyLoadingFilter</filter-name>
    <url-pattern>/mvc/*</url-pattern>
</filter-mapping>

Once the you have this in place, every call in hibernate made within that call will use the same session:

@Autowired
protected SessionFactory sessionFactory;

protected Session getSession() {

    return SessionFactoryUtils.getSession(sessionFactory, true);
}

However, as Peter Gwiazda says, you may or may not want to do this depending on the scale and complexity of your application. It sounds like your objects are quite complex so having your views essentially trigger more SQL statements as you traverse your entity in your JSP or whatever is not going to lead to great performance.

It is generally a better pattern to convert your object into a DTO with just what your view needs and limit the amount of data you fetch back from your database.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM