Discussion hibernate lazy loading

sponsored links
Hibernate lazy initialization error is the use of development projects in the most common mistakes. If the configuration of a class or collection of search strategy of delay, it must be when the agent or agent class instance is a collection of persistent state (that is in Session range) time to initialize it. Initialized in the free state only if it will produce delayed initialization error.

The following elements of the Customer.hbm.xml file the lazy attribute set <class> true, that the use of delayed search strategies:

<class name="mypack.Customer" table="CUSTOMERS" lazy="true">

When the Executive Session of the load () method, Hibernate does not immediately execute the query CUSTOMERS table select statement, only the Customer class returns an instance of the proxy class, the proxy class with the following characteristics:

(1) from Hibernate dynamically generated at run time, it extends the Customer class Customer class so it inherits all the properties and methods, but its implementation is transparent to applications.
(2) When Hibernate creates a proxy class instance of Customer, just initialize its OID attribute, other attributes are all null, so the proxy class instance takes very little memory.
(3) When the application first visit to the Customer agent class instance (for example, call customer.getXXX () or customer.setXXX () method), Hibernate will initialize the proxy class instance, in the select statement to perform the initialization process, Customer real object loaded from the database all the data. But an exception, and that is when the application instance of the proxy class to access Customer getId () method, Hibernate does not initialize the proxy class instance, because when creating the proxy class instance OID to exist, do not have to query the database .

Tip: Hibernate uses CGLIB tool to generate proxy classes persistent class. CGLIB is a powerful Java byte code generation tool, it can expand dynamically generated runtime Java class or Java interface to implement the proxy class. More knowledge about the CGLIB, please refer to: http://cglib.sourceforge.net/.

The following code to pass Session of the load () method loads the Customer object, then access its name attribute:

tx = session.beginTransaction ();
Customer customer = (Customer) session.load (Customer.class, new Long (1));
customer.getName ();
tx.commit ();

Running session.load () method, Hibernate does not execute any select statement, only the Customer class returns an instance of the proxy class, it's OID is 1, which is the load () method of the second parameter specified. When an application calls customer.getName () method, Hibernate initializes an instance of the proxy class Customer, Customer object is loaded from the database data, perform the following select statement:

select * from CUSTOMERS where
select * from ORDERS where CUSTOMER_ID = 1;

When the elements of the lazy attribute <class> true, would affect the Session of the load () method of the various run-time behavior, the following example.

1. If you load the Customer object does not exist in the database, Session of the load () method does not throw an exception, only when running customer.getName () method will throw the following exception:

ERROR LazyInitializer: 63 - Exception initializing proxy
net.sf.hibernate.ObjectNotFoundException: No row with the given identifier exists: 1, of class:
mypack.Customer

2. If the Session range, the application not visited Customer object, then the Customer instance of the proxy class has not been initialized, Hibernate will not execute any select statement. The following code attempts to close the Session object after free access to Customer:

tx = session.beginTransaction ();
Customer customer = (Customer) session.load (Customer.class, new Long (1));
tx.commit ();
session.close ();
customer.getName ();

As Customer reference variable customer references an instance of the proxy class within the Session has not been initialized, so in the implementation of customer.getName () method, Hibernate throws the following exception:

ERROR LazyInitializer: 63 - Exception initializing proxy
net.sf.hibernate.HibernateException: Could not initialize proxy - the owning Session was closed

Thus, Customer proxy instance of the class only in the context of the current Session to be initialized.

3. net.sf.hibernate.Hibernate class initialize () static method is used within the Session explicitly initialize proxy class instance, isInitialized () method is used to determine whether an instance of the proxy class has been initialized. For example:

tx = session.beginTransaction ();
Customer customer = (Customer) session.load (Customer.class, new Long (1));
if (! Hibernate.isInitialized (customer))
Hibernate.initialize (customer);
tx.commit ();
session.close ();
customer.getName ();

The above code in the Session through the Hibernate classes within the initialize () method to explicitly initialize the Customer agent class instance, so when the Session is closed, you can normally access the Customer free object.

4. When an application to access the proxy class instance getId () method, Hibernate does not initialize the proxy class instance trigger the behavior, such as:

tx = session.beginTransaction ();
Customer customer = (Customer) session.load (Customer.class, new Long (1));
customer.getId ();
tx.commit ();
session.close ();
customer.getName ();

When an application to access customer.getId () method, the method simply returns an instance of the proxy class OID Customer value, without having to query the database. Customer is always the reference variable refers to the Customer agent has not been initialized class instance, so when the Executive Session closed after customer.getName () method, Hibernate throws the following exception:

ERROR LazyInitializer: 63 - Exception initializing proxy
net.sf.hibernate.HibernateException: Could not initialize proxy - the owning Session was closed

Solution:

Because hibernate using lazy = true, so that when you use hibernate query to return the actual proxy class using cglib enhanced, but did not actually fill; when you in the front, use it to value (getXXX), the time Hibernate will execute the query to the database, and populate the object, but at this time if the proxy class associated with this session has been closed off, it will have kind of error.
When doing one to many, sometimes "could not initialize proxy - clothe owning Session was sed, this seems to hibernate cache issue. Problem-solving: the need to set the <many-to-one> where lazy =" false ". But may cause another exception called

failed to lazily initialize a collection of role: XXXXXXXX, no session or session was closed

Solution: Add in web.xml
<filter>
<filter-name> hibernateFilter </ filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</ Filter-class>
</ Filter
<filter-mapping>
<filter-name> hibernateFilter </ filter-name>
<url-pattern> *. do </ url-pattern>
</ Filter-mapping>
Can;

Reference:
Hibernate with lazy loading:

Hibernate object-relational mapping to provide the delay and non-delay object initialization. Non-lazy when it reads an object and the object will all read it together with other objects. This sometimes leads to hundreds (if not thousands of words) select statement is executed when the object is read. This problem sometimes occurs when using the two-way relationship, often resulting in the entire database in the initialization phase is read out. Of course, you can take the trouble to check each object and other objects of the relationship, and to remove the most expensive, but in the end, we may lose this to the ORM tools available facilities.

One obvious solution is to use lazy loading mechanism provided by Hibernate. This strategy is only one object initialization call it-to-many or many to many relationships between objects only to read out. This process is transparent to the developer, and only got a few requests for database operations, it will be more obvious in performance. One drawback of this technique is to delay load the technical requirements of a Hibernate session when the object is used to has been open. This will be by using the DAO pattern to abstract the persistence layer when a major problem. Persistence mechanisms in order to completely abstract, all the database logic, including open or close the session, can not appear in the application layer. The most common is a simple interface that implement DAO implementation class to encapsulate the database logic completely. A fast but clumsy solution is to abandon DAO mode, add the database connection logic to the application layer. This may be an effective small applications, but in large systems, this is a serious design flaw prevented the system scalability.

Delays in loading Web layer

Fortunately, Spring framework Hibernate lazy loading with the integration of DAO pattern provides a convenient solution. For those not familiar with Spring and Hibernate integration of people, I will not discuss too many details here, but I suggest you go to learn Hibernate and Spring integration of data access. A Web application as an example, Spring provides a OpenSessionInViewFilter and OpenSessionInViewInterceptor. We can choose a class to achieve the same functionality. The only difference the two methods is that interceptor in the Spring container and configured to run in the context of web applications, and Filter before running in the Spring and configured in the web.xml. Regardless of what they are requesting the current session with the current (database) when you open the thread-bound Hibernate session. Once bound to the thread, this opens a Hibernate session in DAO implementation class can be transparently used. This session will load the database values for the delay in view of the object remains open. Once completed this logical view, Hibernate session in the Filter's doFilter method or methods Interceptor's postHandle be closed. Here is an example configuration of each component:

Interceptor configuration:

<beans>
<Bean
class = "org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="openSessionInViewInterceptor"/>
</ List>
</ Property>
<property name="mappings">

</ Bean>

<Bean name = "openSessionInViewInterceptor"
class = "org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor">
<property name="sessionFactory"> <ref bean="sessionFactory"/> </ property>
</ Bean>
</ Beans>

Filter configuration

<web-app>

<filter>
<filter-name> hibernateFilter </ filter-name>
<filter-class>
org.springframework.orm.hibernate.support.OpenSessionInViewFilter
</ Filter-class>
</ Filter>

<filter-mapping>
<filter-name> hibernateFilter </ filter-name>
<url-pattern> *. spring </ url-pattern>
</ Filter-mapping>

</ Web-app>

Hibernate Dao implementation of the interface to use to open the session is very easy. In fact, if you have used the Spring framework to achieve your Hibernate Dao, you probably do not need to change anything. Public HibernateTemplate convenience to access the database component into a piece of cake, but only through the DAO interface, this component can access to the database. Here is an example of the DAO:

public class HibernateProductDAO extends HibernateDaoSupport implements ProductDAO (

public Product getProduct (Integer productId) (
return (Product) getHibernateTemplate (). load (Product.class, productId);
)

public Integer saveProduct (Product product) (
return (Integer) getHibernateTemplate (). save (product);
)

public void updateProduct (Product product) (
getHibernateTemplate (). update (product);
)
)

Use lazy loading in the business logic layer

Even in view of the outside, Spring framework also HibernateInterceptor through the use of AOP interceptors to make it easy to become lazy. The Hibernate interceptor will be called transparently in the Spring application context configuration in the business object method to intercept the request down, before calling the method to open a Hibernate session, and then after completing the implementation of the method will then close. Let's look at a simple example, suppose we have an interface BussinessObject:

public interface BusinessObject (
public void doSomethingThatInvolvesDaos ();
)
BusinessObject class BusinessObjectImpl implements the interface:

public class BusinessObjectImpl implements BusinessObject (
public void doSomethingThatInvolvesDaos () (
/ / Lots of logic that calls
/ / DAO classes Which access
/ / Data objects lazily
)
)

Spring application context by some of the configuration, we can intercept calls BusinessObject way down, and then make its way to support lazy loading. A look at the following program fragment:

<beans>
<bean>
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</ Property>
</ Bean>
<bean>
<property name="someDAO"> <ref bean="someDAO"/> </ property>
</ Bean>
<bean>
<property name="target"> <ref bean="businessObjectTarget"/> </ property>
<property name="proxyInterfaces">
<value> com.acompany.BusinessObject </ value>
</ Property>
<property name="interceptorNames">
<list>
<value> hibernateInterceptor </ value>
</ List>
</ Property>
</ Bean>
</ Beans>

When businessObject is invoked, HibernateInterceptor open a Hibernate session, and call the request object passed to the BusinessObjectImpl. When BusinessObjectImpl after implementation, HibernateInterceptor transparent closed session. The application layer of code do not understand any persistence logic, or to achieve a lazy loading.

Delay in the loading unit test to test

Finally, we need to use the J-Unit test our lazy loading process. We can easily TestCase class by overriding the setUp and tearDown methods to achieve this requirement. I prefer to use the convenience abstract class as my base class for all tests.

public abstract class MyLazyTestCase extends TestCase (

private SessionFactory sessionFactory;
private Session session;

public void setUp () throws Exception (
super.setUp ();
SessionFactory sessionFactory = (SessionFactory) getBean ("sessionFactory");
session = SessionFactoryUtils.getSession (sessionFactory, true);
Session s = sessionFactory.openSession ();
TransactionSynchronizationManager.bindResource (sessionFactory, new SessionHolder (s));

)

protected Object getBean (String beanName) (
/ / Code to get objects from Spring application context
)

public void tearDown () throws Exception (
super.tearDown ();
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource (sessionFactory);
Session s = holder.getSession ();
s.flush ();
TransactionSynchronizationManager.unbindResource (sessionFactory);
SessionFactoryUtils.closeSessionIfNecessary (s, sessionFactory);
)
)
  • del.icio.us
  • StumbleUpon
  • Digg
  • TwitThis
  • Mixx
  • Technorati
  • Facebook
  • NewsVine
  • Reddit
  • Google
  • LinkedIn
  • YahooMyWeb

Related Posts of Discussion hibernate lazy loading

  • hibernate fourteenth chapter of the study

    hibernate internal cache hibernate cache is divided into two levels: level cache (session) and the secondary cache (sessionFactory level) The role of cache is mainly used to improve performance, can be simply understood as a Map; the use of caching involv

  • Javascript implementation of the category

    Javascript implementation of the category (Reprint: http://www.cnitblog.com/CoffeeCat/archive/2008/02/25/40138.html) Javascript does not support object-oriented, it does not address access control, it does not define categories of keywords class, it ...

  • Firebug Guide (four) --- how to use the Firebug command line API to provide debugging js procedures (below)

    Introduction: Firebug command line are in one of the most useful features. If you have been using Visual Studio (referred to as VS) the experience of development projects, they should know you in the use of VS debugging procedures, "the immediate win

  • DWR trial

    1, call not return value and parameters JAVA Ways 1.1, dwr.xml configuration <dwr> <allow> <create creator="new" javascript="testClass"> <param name="class" value="com.dwr.TestClass" /> ...

  • Express instance to use AJAX

    Summary Introduction: AJAX-wide known as "Asynchronous JavaScript and XML" (Asynchronous JavaScript and XML), its core only JavaScript, XMLHTTPRequest and DOM. XMLHTTP is the first application of Microsoft, IE (IE5 and above) by allowing develop

  • Spring and Hibernate Integration

    1. Management SessionFactory Spring Integration to use Hibernate, we do not need to file hibernate.cfg.xml. First, in the applicationContext.xml to configure the data source (dataSource) bean and the session factory (sessionFactory) bean. Among them, the

  • [Have resolved] how to give rails of the model class of congestive (include / extent module)

    Has been resolved Please visit: http://henrik.nyh.se/2008/02/rails-model-extensions 1: the introduction of new features to the controller My approach: I tried to introduce in the application controller extra modules: require "string" This "string

  • hibernate study of the second

    Persistence of three main points: 1, a statement for persistent fields accessors (accessors) and whether the variable signs (mutators) Property statement is not necessarily required for the public's. Hibernate can be default, protected or private ...

  • Application of spring struts2.0 hibernate HQL

    Therefore, in the development of statistical inquiry system, as far as possible through the use of select statement to write the required query property way back relational data, and avoid using the first query return persistent object (in this way are in

  • Hibernate secondary cache

    Hibernate cache: 2-bit cache, also known as process-level cache or SessionFactory level cache, secondary cache can be shared by all of the session Cache configuration and the use of: Will echcache.xml (the document code in hibernate package directory ...

blog comments powered by Disqus
Recent
Recent Entries
Tag Cloud
Random Entries