Hibernate delay-loaded legend-level error Org.hibernate.LazyInitializationException:could not initialize proxy-no session_hibernate

Source: Internet
Author: User
Tags aop sessions

Many people will come across this mistake.

Http://hi.baidu.com/itroad/blog/item/6d12f01fe0b8dc0d314e1531.html

Could not initialize proxy-no session Wednesday, December 03, 2008 06:59 p.m.

Original address: http://www.wozaishuo.com.cn/article.asp?id=367

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

is simple to understand because you use lazy=true, so that when you hibernate data from a database, you will not be able to find the associated object, but save a way to get a worthwhile method, 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 show the data, the session has already been closed in DAO, how can we solve this anomaly?

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

2. I haven't tried, but I've heard that it should be possible.
Add program code <filter>
     <filter-name>hibernatefilter</filter-name to Web.xml >
     <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. Fetch or INNER JOIN FETCH syntax with a LEFT join.
For example: From Item I left join fetch I.parentitem II
Explain that the item table is a self associated table, and its associated relationship is 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 The program code private Item ParentItem;


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

I hope I can help you solve the problem, so I am content.

Below turn a good article, also speak could not initialize proxy-no the session problem!
Could not initialize Proxy-the owning session is closed.
Many places have been well-known solutions, to explain the problem and rewrite it again.

But in this context, about the lazy mechanism:

Lazy initialization errors are the most common errors in using Hibernate development projects. If a deferred retrieval policy is configured on a class or collection, it must be initialized when the proxy class instance or collection of proxies is in a persisted state (that is, within session scope). If it is initialized in a free state, a delay initialization error is generated.

The following Customer.hbm.xml file's <class> element's Lazy property is set to True to indicate the use of a deferred retrieval policy:

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

When the session's load () method is executed, hibernate does not immediately execute a SELECT statement that queries the Customers table, only returns an instance of the proxy class for the customer class, which has the following characteristics:

(1) dynamically generated by hibernate at runtime, 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, only its OID attribute is initialized and the other properties are null, so the proxy class instance consumes very little memory.
(3) When an application accesses the customer proxy class instance for the first time (for example, by invoking the customer.getxxx () or Customer.setxxx () method), Hibernate initializes the proxy class instance and executes the SELECT statement during initialization. Actually loads all the data from the customer object from the database. The exception, however, 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 a proxy class for the persisted class. Cglib is a powerful Java bytecode generation tool that can dynamically generate extended Java classes or proxy classes that implement Java interfaces while the program is running. For more information on Cglib, please refer to: http://cglib.sourceforge.net/.

The following code loads the customer object first 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 ();

When you run the Session.load () method, Hibernate does not execute any SELECT statements, simply returns an instance of the proxy class for the customer class, whose OID is 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 data from the customer object 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 load () method of the session 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 does not have access to the customer object throughout the session, instances of the customer proxy class are not initialized and hibernate does not execute any SELECT statements. The following code attempts to access the customer free object after the session is closed:

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

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

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

Thus, instances 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 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 explicitly initializes the customer proxy class instance in 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. When an application accesses the GetID () method of a proxy class instance, the behavior of the Hibernate initialization proxy class instance is not triggered, 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 references a customer proxy class instance that has not been initialized, and then executes the Customer.getname () method after the session is closed, hibernate throws the following exception:

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

Workaround:

Since Hibernate employs lazy=true, it returns a proxy class that is actually used for cglib enhancements when you use the Hibernate query, but it is not actually populated; When you use it to get value (GETXXX) on the front end, At this point hibernate will go to the database to execute the query and populate the object, but if the session associated with this proxy class has been shut down, it will produce a kind of error.
In a couple of moments, there are "could not initialize proxy-clothe owning sessions was SED, which seems to be a hibernate cache problem. Problem solving: Need <many-to-one> Set lazy= "false" in. But there may be another exception called

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

This exception solution please see "Failed to lazily initialize a collection of the" Hibernate exception in 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>
is OK;

For reference:
Hibernate and deferred loading:

Hibernate Object Relational mappings provide deferred and non deferred object initialization. Non-deferred loading reads an object together with all the other objects associated with the object. This sometimes causes hundreds, if not thousands, of SELECT statements to be executed when the object is read. This problem sometimes occurs when a two-way relationship is used, which often causes the entire database to be read out at the initialization stage. Of course, you can take the trouble to check each object's relationship with other objects and remove the most expensive ones, but in the end, we may lose the convenience we wanted to get in the ORM tool.


An obvious solution is to use the deferred loading mechanism provided by hibernate. This initialization strategy reads only the relational object when an object invokes its One-to-many or many-to-many relationship. This process is transparent to developers, and requires only a small number of database operation requests, resulting in a more significant performance boost. One drawback of this technique is that the delay-loading technique requires a hibernate session to remain open while the object is in use. This becomes a major problem when the persistence layer is abstracted by using the DAO pattern. In order to completely abstract the persistence mechanism, all database logic, including opening or closing sessions, cannot appear at the application layer. Most commonly, some DAO implementation classes that implement a simple interface encapsulate the database logic completely. A quick but clumsy workaround is to discard the DAO schema and add the database connection logic to the application tier. This may be useful for some small applications, but in large systems this is a serious design flaw that hinders the scalability of the system.

Delay loading at the web layer

Fortunately, the spring framework provides a convenient workaround for hibernate deferred loading and the DAO schema consolidation. For those unfamiliar with spring and hibernate integration, I'm not going to discuss much of the details here, but I recommend that you understand the data access that Hibernate and spring have integrated. As an example of a Web application, Spring provides Opensessioninviewfilter and Opensessioninviewinterceptor. We are free to select a class to achieve the same function. The only difference between the two methods is that interceptor runs in the spring container and is configured in the context of the Web application, and filter runs before spring and is configured in Web.xml. Either way, they are requesting that the current session be opened with the current (database) thread binding to open the Hibernate session. Once you have 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 the value objects in the database. Once this logical view is complete, the hibernate session is closed in the Dofilter method of the filter or in the Posthandle method of the Interceptor. The following is a sample configuration for each component:


Interceptor Configuration:

<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 the Hibernate DAO interface to use an open session. In fact, if you've already used the spring framework to implement your Hibernate Dao, chances are you don't need to change anything. Convenient hibernatetemplate common components make accessing the database a piece of cake, and the DAO interface can access the database only through this component. Here 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 deferred loading in the business logic layer

Even outside the view, the spring framework makes lazy loading easy to implement by using the AOP interceptor Hibernateinterceptor. This hibernate interceptor transparently intercepts requests for methods that are configured in the context of the spring application, opens a hibernate session before the method is invoked, and then closes the session after the method has finished 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 invokes Businessobject, and then let its methods support lazy loading. Look at one of the following pieces of the program:


<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 invoked, Hibernateinterceptor opens a hibernate session and passes the call request to the Businessobjectimpl object. When Businessobjectimpl execution completes, Hibernateinterceptor closes the session transparently. The application-tier code does not need to understand any persistence layer logic or implement deferred loading.


Testing for deferred loading in unit tests

Finally, we need to test our delay loader with J-unit. 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 the use of 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 of objects, then each load one to execute a lot of HQL statements, it is conceivable that this efficiency problem, especially when using the list. So it's not practical, and that's the case with "using deferred loading in the business logic layer" as described above.

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 several things to say:

1. Opensessionview mode is not always available in quartz

2. In the process of intercepting after spring, it is not possible to take advantage of Opensessionview if the child objects in the object are intercepted

There are a lot of things can not be used, then how to solve it. Some people say that is lazy=false, you want to solve a simple quartz when the whole Web project to adjust the load seems inappropriate.

So 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 call the manual loading is more appropriate and convenient, but it is estimated to be a few more lines of code, think about

2011-1-17 Latest Additions

So you can't get it, because the session is closed, mainly because your one-to-many lazy set to True, if you do need to delay loading, you can call Hibernate.initialize before the session is closed ( 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.

This method has been mentioned in the previous article, and today it is noted here.

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.