Best way to handle Hibernate Sessions in a layered Spring MVC Web application
If we have a web application which has
- heavy UI (Spring MVC + JQuery with JSON)
- Hibernate with JPA annotations being the domain model
- extend Spring-provided DAO to code DAO layer
- JBOSS being the app server with Oracle as backend
- Datasource (JNDI) based connection pooling (Not an XA rather Local data source)
- also has access to multiple data sources (dealing with multiple DB)
Behaviorally, lot of Data retrieval (70%) and update of data being 30%
What would be the best practices for the following to effectively consume DB connections and also see to 开发者_如何学Cthat there is no much leakage at connection usage?- would it be better to opt for Hibernate template based DAOs?
- What kind of transaction manager would be suggest-able and should we go for AOP-based transaction managementWhere
- where to instantiate session and and where to close the sessions to effectively consume connections from connection pooling.
- It is true that we need to handle transactions from Service layer but what happens to sessions would they be waiting for longer time (we are not using any opensessioninviewFilter)
- which layer is better to handle the checked exceptions (business exceptions) and runtime exceptions.
Sorry for this being bit lengthier question, however I see that this is being a common query and I tried consolidating it. Appreciate your patience and guidance. Thanks for your help.
This sounds like a pretty typical Spring/Hibernate application, so I would recommend following current best practices, which I recently outlined in another answer. Specifically:
- Do not extend Spring DAO support classes or use HibernateTemplate. Use the @Repository annotation combined with component scanning, and directly inject the SessionFactory into your DAO.
- Use Spring's HibernateTransactionManager, and definitely use declarative transaction management via @Transactional as your default approach.
- Let Spring manage that. It will open sessions just in time for transactions by default, but prefer the open session in view pattern enabled by Spring's OpenSessionInViewFilter.
- See #3.
- Always handle exceptions where they should be handled--in other words, this is a design decision. Note, however, that the Spring transaction framework by default rolls back on unchecked exceptions, but not checked, to match the behavior of the EJB spec. Make sure to set the proper rollback rules (see previous link) anywhere you use checked exceptions.
Additionally, use a connection pool, obviously. Apache Commons DBCP is a great choice. "Not much leakage in connection usage" isn't enough. You have to have zero connection leakage. Depending on Spring to manage your resources will help ensure this. As for any other performance issues, don't try to optimize prematurely. Wait until you see where your problem areas are, and then figure out the best way to solve each one individually. Since your bottlenecks will most likely be database-related, check out the performance chapter of the Hibernate reference to get an idea what you're up against. It covers the important concepts of caching and fetching strategies.
- Use JPA
EntityManager
directly in your DAOs. Be sure not to mark it as Extended - Prefer
<tx:annotation-driven />
and@Transactional
- only on the service layer - The transaction manager also opens and closes sessions (if one doesn't exist already in the thread). Here it is good to know that sessions are session-per-request. Each request(=thread) has a separate session instance. But a database connection is created only if one is needed, so even if there is a transaction manager around all methods, needless connections won't be opened.
- read-only transactions - use
@Transactional(readOnly=true)
in cases when there is only data retrieval - caching - utilize hibernate 2nd level cache to put entities in memory (instead of fetching them from the database each time)
- avoid
OpenSessionInView
and lazy collections. This is subjective, but in my opinion all objects that leave the service layer must be initialized. For small collections (for ex. list of roles) you can have eager collections. For bigger collections use HQL queries.
精彩评论