Org.hibernate.LazyInitializationException:could not initialize Proxy-no Session

Source: Internet
Author: User

This error is common in <many-to-on>, and the literal meaning cannot be initialized because the session is closed.

The simple understanding is that you use lazy=true so that hibernate does not look up the associated object when it is tuning data from the database, but instead saves a fetch-worthy method that, when you use the getxxx () call, Hiberante will use this saved method to fetch data from the database. And often we use GETXXX () in the JSP page to prepare to display the data, the session has already been closed in the DAO, how can we solve this anomaly?

There are three simple ways to say it:
1. Set the lazy to false, the most 2 way, but the simplest, simple is beautiful, there will still be a lot to use this way to solve similar problems.

2. I haven't tried, but I've heard that it should be possible.
Add to Web. xml

Program Code <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>



3. I use the method, but also I think the more good method, flexibility is better. Use the LEFT join fetch or INNER JOIN fetch syntax.
Example: From Item I left join fetch I.parentitem II
Explain that the item table is a self-correlating table, and its associated relationships are configured in Hbm.xml.
As follows:

Program code <many-to-one name= "ParentItem" lazy= "false" fetch= "join" class= "Cn.sports.matchs.model.Item" >
<column name= "parent_id" ></column>
</many-to-one>


In the Item class

Program code private Item ParentItem;


Using the LEFT join fetch can be a perfect solution to this problem.

I hope to help you solve the difficulties, so I am satisfied.

The following turn a good article, also speak could not initialize proxy-no session problem!
Could not initialize Proxy-the owning Session was closed!
Many places have been well-known solutions, in order to illustrate the problem rewrite again!

But say something about the lazy mechanism:

Lazy initialization errors are the most common errors when you use Hibernate to develop projects. If a deferred retrieval policy is configured on a class or collection, it must be initialized when the proxy class instance or proxy collection is persisted (that is, within the session scope). If it is initialized in a free state, a lazy initialization error occurs.

The following sets the lazy property of the <class> element of the Customer.hbm.xml file to True, indicating the use of a deferred retrieval strategy:

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

When executing the session's load () method, Hibernate does not immediately execute a SELECT statement that queries the Customers table, returning only instances of the proxy class of the customer class, which is characterized by the following characteristics:

(1) dynamically generated by hibernate at run time, it extends the customer class, so it inherits all the properties and methods of the customer class, but its implementation is transparent to the application.
(2) When Hibernate creates an instance of the customer proxy class, it only initializes its OID property, and all other properties are null, so this proxy class instance consumes little memory.
(3) When an application accesses the customer proxy class instance for the first time (for example, by calling the Customer.getxxx () or Customer.setxxx () method), Hibernate initializes the proxy class instance, executes the SELECT statement during initialization, All data from the customer object is actually loaded from the database. One exception is that when an application accesses the GetID () method of the Customer proxy class instance, Hibernate does not initialize the proxy class instance because the OID exists when the proxy class instance is created and does not have to be queried in the database.

Tip: Hibernate uses the Cglib tool to generate proxy classes for persisted classes. Cglib is a powerful Java bytecode generation tool that can dynamically generate extended Java classes or proxy classes that implement Java interfaces when the program is run. For more information on Cglib, please refer to: http://cglib.sourceforge.net/.

The following code first loads the customer object through the session's load () method, and then accesses its Name property:

tx = Session.begintransaction ();
Customer customer= (Customer) Session.load (Customer.class,new Long (1));
Customer.getname ();
Tx.commit ();

Hibernate does not execute any SELECT statements when running the Session.load () method, only returns an instance of the proxy class for the customer class, with an OID of 1, which is specified by the second parameter of the load () method. When the application calls the Customer.getname () method, Hibernate initializes the customer proxy class instance, loads the customer object's data from the database, and executes the following SELECT statement:

SELECT * from CUSTOMERS where id=1;
SELECT * from OrDERS where customer_id=1;

When the <class> element's Lazy property is true, it affects the various run-time behaviors of the session's load () method, as illustrated below.

1. If the loaded customer object does not exist in the database, the session's load () method does not throw an exception, and the following exception is thrown only when the Customer.getname () method is run:

ERROR lazyinitializer:63-exception Initializing Proxy
Net.sf.hibernate.ObjectNotFoundException:No row with Thegiven identifier exists:1, of class:
Mypack. Customer

2. If the application has not accessed the customer object throughout the session, the instance of the customer proxy class is never initialized and hibernate does not execute any SELECT statements. The following code attempts to access the customer free object after closing the session:

tx = Session.begintransaction ();
Customer customer= (Customer) Session.load (Customer.class,new Long (1));
Tx.commit ();
Session.close ();
Customer.getname ();

Since the instance of the customer proxy class referenced by the customer reference variable is never initialized within the session scope, hibernate throws the following exception when executing the Customer.getname () method:

ERROR lazyinitializer:63-exception Initializing Proxy
Net.sf.hibernate.hibernateexception:couldnotinitializeproxy-theowningsessionwasclosed

Thus, an instance of the customer proxy class can be initialized only within the current session scope.

3. The Initialize () static method of the Net.sf.hibernate.Hibernate class is used to explicitly initialize the proxy class instance within the session scope, and the isinitialized () method is used to determine whether the proxy class instance 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 explicitly initializes the customer proxy class instance within the session scope through the Hibernate class's Initialize () method, so the customer free object can be accessed normally when the session is closed.

4. Hibernate initializes the behavior of the proxy class instance when the application accesses the GetID () method of the proxy class instance, for example:

tx = Session.begintransaction ();
Customer customer= (Customer) Session.load (Customer.class,new Long (1));
Customer.getid ();
Tx.commit ();
Session.close ();
Customer.getname ();

When an application accesses the Customer.getid () method, the method returns the OID value of the customer proxy class instance directly, without querying the database. Because the reference variable customer always refers to an instance of the customer proxy class that is not initialized, Hibernate throws the following exception when the session closes and then executes the Customer.getname () method:

ERROR lazyinitializer:63-exception Initializing Proxy
Net.sf.hibernate.hibernateexception:couldnotinitializeproxy-theowningsessionwasclosed

Workaround:

Since hibernate uses lazy=true so that when you query with hibernate, it returns the proxy class that is actually enhanced with cglib, but it is not actually populated, and when you use it to fetch values (GetXXX) at the front end, Hibernate then executes the query to the database and populates the object, but at this point the session associated with the proxy class is closed, resulting in a kind of error.
In a couple of times, there are sometimes "could not initialize Proxy-clothe owning Session is sed, which seems to be Hibernate's caching problem." Problem solving: Need <many-to-one> Set lazy= "false" in the But it is possible to throw another exception called

Failed to lazily initialize a collection of role:xxxxxxxx, no session or session was closed

This exception solution please see the "failed to lazily initialize a collection of role exception" in the hibernate exception of my blog (http://hi.baidu.com/kekemao1)

?
Workaround: 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>
It can be;

Referenced by:
Hibernate with lazy loading:

Hibernate Object Relational mappings provide deferred and non-deferred object initialization. Non-lazy loading reads an object in conjunction with all other objects related to the object. This can sometimes result in hundreds of (if not thousands) of SELECT statements being executed when the object is read. This problem sometimes occurs when a bidirectional relationship is used, which often results in the entire database being read at the initialization stage. Of course, you can take the trouble to check each object's relationship with other objects and put those most expensive deletions, but in the end, we might lose the convenience that we wanted to get in the ORM tool.


An obvious workaround is to use the lazy load mechanism provided by Hibernate. This initialization policy reads the relational object only when one of the objects calls it for a pair of many or many-to-many relationships. This process is transparent to the developer, and there are only a few requests for database operations, resulting in significant performance gains. One drawback of this technique is that a lazy-loading technique requires that a hibernate session be kept open while the object is in use. This becomes a major problem when abstracting the persistence layer by using the DAO pattern. In order to completely abstract the persistence mechanism, all database logic, including opening or closing sessions, cannot occur at the application level. Most commonly, some DAO implementation classes that implement simple interfaces encapsulate the database logic completely. A quick but clumsy solution is to discard the DAO pattern and add the database connection logic to the application layer. This may be useful for small applications, but in large systems, this is a serious design flaw that hinders the scalability of the system.

Lazy loading at the Web tier

Fortunately, the spring framework provides a convenient workaround for hibernate lazy loading and the integration of DAO patterns. For those of you who are not familiar with the integration of spring and hibernate, I will not discuss too much detail here, but I recommend that you understand Hibernate's integrated data access with spring. As an example of a Web application, Spring provides Opensessioninviewfilter and Opensessioninviewinterceptor. We are free to choose a class to implement the same functionality. The only difference between the two approaches is that interceptor runs in the spring container and is configured in the context of the Web application, and the filter runs before spring and is configured in XML. Whichever they are, they are requesting the hibernate session to be opened with the current session bound to the current (database) thread. Once bound to a thread, this open hibernate session can be used transparently in the DAO implementation class. This session remains open for a view that delays loading a value object in the database. Once this logical view is complete, the hibernate session is closed in the Dofilter method of the filter or the Posthandle method of the Interceptor. The following is a sample configuration for each component:


Configuration of the Interceptor:

<beans>
<bean id= "UrlMapping"
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>

Configuration of filter

<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>


It is easy to implement Hibernate's DAO interface to use open sessions. In fact, if you've already used the spring framework to implement your Hibernate Dao, chances are you don't need to change anything. The convenient hibernatetemplate common component makes accessing the database a piece of cake, and the DAO interface can only access the database through this component. The following is an example of 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);
}
}

Using lazy loading in the business logic layer

Even outside the view, the spring framework makes it easy to implement lazy loading by using the AOP interceptor Hibernateinterceptor. This hibernate interceptor transparently intercepts requests for methods that are configured in a business object in the context of the spring application, opens a hibernate session before invoking the method, and then closes the session after the method finishes executing. Let's look at a simple example, assuming we have an interface Bussinessobject:


Public interface Businessobject {
public void Dosomethingthatinvolvesdaos ();
}
Class Businessobjectimpl implements the Businessobject interface:

public class Businessobjectimpl implements Businessobject {
public void Dosomethingthatinvolvesdaos () {
Lots of logic that calls
DAO Classes which access
Data Objects lazily
}
}


With some configuration in the context of the spring application, we can intercept the method that calls Businessobject, and then make its method support lazy loading. Take a look at one of the following program fragments:


<beans>
<bean id= "Hibernateinterceptor" class= "Org.springframework.orm.hibernate.HibernateInterceptor" >
<property name= "Sessionfactory" >
<ref bean= "Sessionfactory"/>
</property>
</bean>
<bean id= "Businessobjecttarget" class= "Com.acompany.BusinessObjectImpl" >
<property name= "Somedao" ><ref bean= "Somedao"/></property>
</bean>
<bean id= "Businessobject" class= "Org.springframework.aop.framework.ProxyFactoryBean" >
<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 called, Hibernateinterceptor opens a hibernate session and passes the call request to the Businessobjectimpl object. When the Businessobjectimpl execution completes, the session is closed transparently by Hibernateinterceptor. The application layer's code does not need to know any persistence layer logic or implement deferred loading.


To test lazy loading in a unit test

Finally, we need to use j-unit to test our Lazy loader program. We can easily implement this requirement by rewriting the setup and Teardown methods in the TestCase class. I prefer to use this handy abstract class as the base class for all my test classes.


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);
}
}



We first say that using lazy=false to solve the problem, this method is very useful, but in the actual process is not practical, if you have an object associated with several or even more than 10 self-object, then every time you load a word to execute a lot of HQL statements, you can imagine this efficiency problem, especially when using the list. So it is not practical, and in the above mentioned "using lazy loading in the business Logic layer" is also the case.

Many friends who use the web like to use Opensessionview to load the problem. Good I also like to use, simple and convenient. But there are a few things to say:

1. Opensessionview mode is not always available in quartz

2. In the process of blocking after spring, it is not possible to take the sub-objects in the interception object using Opensessionview

There are a lot of things that can't be used, so how to solve them. Some people say that is lazy=false, you want to solve a simple quartz when the entire Web project to adjust the load seems inappropriate.

What to do, I think this time can consider the use of SQL statements to reload the proxy class, so that when you want to invoke the manual loading is more appropriate and convenient, but estimated to be more than a few lines of code, think about

2011-1-17 Latest Additions

So you can not get, because this time the session has been closed, mainly because of your one-to-many in lazy set to True, if you do need to delay loading, before the session is closed, call Hibernate.initialize ( Pojo.getchildren ()) or Pojo.getchildren (). Siz (), let the collection proxy class initialize and load the collection of associated objects, which is also done before the session closes.

Org.hibernate.LazyInitializationException:could not initialize Proxy-no Session

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.