Friday, March 18, 2016

Hibernate Lazy

Lazy: load on demand

Return proxy instead of target object, so load query when you call get functions.

Proxy example:

One-to-one object: HibernateProxy
Set: PersistentSet

So object MUST NOT set as final.


Hibernate default is lazy="true", this will cause error when you use related object when session is already closed.
If set a lot lazy="false", a lot unnecessary query will run, which cause a waste.

Solutions:
  1. Hibernate.initialize
  2. config in hbm.xml, lazy=false
  3. Web filter, openSessionInView
openSessionInView is better than others, since you don't know if you really loading related object or not. All we do just extend life cycle of session.

1. call getXX() function during the session

2. Hibernate.initialize during the session.


Hibernate.initialize(xxx);
//xxx is the property: obj.getXXX()


3. Config hbm.xml

In many-to-one(many side), if set the class to lazy="false"
Hibernate will use left outer join to load related data with the original data in one time.

In one-to-many(one side), if set the set to lazy="false"
Hibernate will first load the object list, then load ALL related objects from separate query for each object.




4. openSessionInView
Set lazy="true"(or just do not set lazy mode)
Make the query session alive, starts from the web filter, until jump out from the web filter.
All hibernate usage then REQUIRED to use getCurrentSession!
And also DONOT close session other than in this filter
This will make session stay open for longer time.

Filter:
for Spring, use Spring provided OpenSessionInViewFilter:

 <!-- OpenSessionInView with spring filter -->
 <filter>
  <filter-name>openSessionInViewFilter</filter-name>
  <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
 </filter>
 <filter-mapping>
  <filter-name>openSessionInViewFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>


Or make filter your self:

public class HibernateSessionFilter extends HttpServlet implements Filter {

 @Override
 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain chain) throws IOException, ServletException {
  Session session = null;
  Transaction tx = null;
  try {
   session = HibernateUtil.getCurrentSession();
   tx = session.beginTransaction();
   chain.doFilter(request, response);
   tx.commit();
  } catch (Exception e) {
   if(tx!=null)tx.rollback();
   throw new RuntimeException(e.getMessage());
  } finally {
   HibernateUtil.closeCurrentSession();
  }

 }

 @Override
 public void init(FilterConfig filterConfig) throws ServletException {

 }

}



Issues for 1 and 2
hard to know when to pre-load, and when to not-pre-load.
If set to pre-load: may waste unnecessary querys
If set to not-pre-load: will cause error when getting related property


No comments:

Post a Comment