I transferred a piece of information about hibernate, which is very good.

Source: Internet
Author: User

In fact, this exception is clearly written, that is, the session is closed and the hibernate entity cannot be operated. There are many such cases, such as writing errors and logical errors.

But let's talk about the lazy mechanism:

Delayed initialization errors are the most common errors in hibernate development projects. If you have configured a latency retrieval policy for a class or set, you must be in the persistent status when the proxy class instance or proxy set is inSessionCan be initialized. If it is initialized only when it is in the Free State, a delayed initialization error will occur.

Set the lazy attribute of the <class> element of the customer. HBM. xml file to true, which indicates that the delayed retrieval policy is used:

<Class name = "mypack. Customer" table = "MERs" lazy = "true">

When executedSessionIn the load () method of, Hibernate does not immediately execute the SELECT statement to query the MERs table, only returns the instance of the customer class proxy class, which has the following characteristics:

(1) It is dynamically generated by hibernate at runtime. It extends the customer class, so it inherits all attributes and methods of the customer class, but its implementation is transparent to applications.
(2) When hibernate creates a customer proxy instance, it only initializes its OID attribute, and other attributes are null. Therefore, this proxy instance occupies very little memory.
(3) When the application accesses the customer proxy instance for the first time (for example, the customer is called. getxxx () or customer. setxxx () method), Hibernate will initialize the proxy class instance, execute the SELECT statement during the initialization process, and truly load all data of the customer object from the database. However, when the application accesses the GETID () method of the customer proxy instance, Hibernate does not initialize the proxy instance because the oId exists when the proxy instance is created, you do not have to query data in the database.

Tip: hibernate uses the cglib tool to generate the proxy class of the persistence class. Cglib is a powerful Java bytecode generation tool that dynamically generates extension Java classes or proxies that implement Java interfaces when the program is running. For more information about cglib, see http://cglib.sourceforge.net /.

The following code first passesSessionLoad () method to load the customer object, and then access its name attribute:

Tx =Session. Begintransaction ();
Customer customer = (customer)Session. Load (customer. Class, new long (1 ));
Customer. getname ();
TX. Commit ();

RunningSession. When the load () method is used, Hibernate does not execute any SELECT statement and only returns the instance of the customer class proxy class. Its 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 of the customer object from the database, and runs the following SELECT statement:

Select * from MERs where id = 1;
Select * from orders where customer_id = 1;

If the lazy attribute of the <class> element is trueSessionThe following is an example of the various runtime behaviors of the load () method.

1. If the loaded customer object does not exist in the database,SessionThe load () method of does not throw an exception. The following exception is thrown only when the customer. getname () method is run:

Error lazyinitializer: 63-Exception initializingProxy
Net. SF. hibernate. objectnotfoundexception: no rowTheGiven identifier exists: 1, of class:
Mypack. Customer

2. IfSessionIf the application has not accessed the customer object, the instance of the customer proxy class will not be initialized and hibernate will not execute any SELECT statement. The following code tries to disableSessionThen access the customer's free object:

Tx =Session. Begintransaction ();
Customer customer = (customer)Session. Load (customer. Class, new long (1 ));
TX. Commit ();
Session. Close ();
Customer. getname ();

Because the instance of the customer proxy class referenced by the customer variable is inSessionThe initialization is not performed in the specified range. Therefore, Hibernate will throw the following exception when executing the customer. getname () method:

Error lazyinitializer: 63-Exception initializingProxy
Net. SF. hibernate. hibernateexception:Cocould Not Initialize Proxy - The Owning Session Was Closed

It can be seen that the customer proxy instance is only in the currentSessionCan be initialized within the specified range.

3.net. SF. hibernate. hibernateInitialize() The static method is used inSessionThe isinitialized () method is used to determine whether the proxy 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 is available inSessionWithin the scope ofInitialize() The method explicitly initializes the customer proxy class instance. Therefore, whenSessionAfter the feature is disabled, you can access the customer's free object normally.

4. When the application accesses the GETID () method of the proxy instance, The Hibernate initialization of the proxy 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 the application accesses the customer. GETID () method, this method returns the oId value of the customer proxy instance directly without querying the database. Because the referenced variable customer always references a non-initialized customer proxy instance, whenSessionAfter it is disabled, run the customer. getname () method. hibernate will throw the following exception:

Error lazyinitializer: 63-Exception initializingProxy
Net. SF. hibernate. hibernateexception:Cocould Not Initialize Proxy - The Owning Session Was Closed

Solution:

Hibernate uses lazy = true. In this way, when you use hibernate for query, the actual proxy class that uses cglib enhancement is returned, but it is not actually filled. When you are at the front end, when it is used to get the value (getxxx), Hibernate will query the database and fill in the object. However, if the session related to this proxy class is closed, an error occurs.
During one-to-many operations, "cocould not initialize proxy-clothe owning session was sed" sometimes appears, which seems to be a cache problem of hibernate. solution: set lazy = "false" in <relative-to-one> ". but it may cause another exception called

Failed to lazily initialize a collection of Role: XXXXXXXX, no session or session was closed

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

?
Solution: add the following content to 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>
You can;

See:
Hibernate and delayed loading:

Hibernate object relationship ing provides delayed and non-delayed object initialization. When reading an object, non-delayed loading reads all other objects related to this object. This sometimes leads to hundreds of (if not thousands) of select statements executed when reading objects. This problem sometimes occurs when two-way relationships are used, and the entire database is often read at the initialization stage. Of course, you can check the relationship between each object and other objects and delete the most expensive objects, but at the end, we may lose the convenience we wanted in the orm tool.

An obvious solution is to use the delayed loading mechanism provided by hibernate. This initialization policy reads a relational object only when an object calls its one-to-many or many-to-many relationship. This process is transparent to developers, and only a few database operation requests are performed, so the performance will be significantly improved. One drawback of this technology is that the delayed loading technology requires that a hibernate session be always open when the object is used. This will become a major problem when the persistent layer is abstracted by using the DAO mode. 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 simple interfaces fully encapsulate the database logic. A fast but clumsy solution is to discard the DAO mode and add the database connection logic to the application layer. This may be effective for some small applications, but in a large system, this is a serious design defect that hinders the scalability of the system.

Perform delayed loading at the web layer

Fortunately, the Spring framework provides a convenient solution for the integration of hibernate delayed loading and DAO mode. For those who are not familiar with spring and hibernate integration, I will not discuss too many details here, but I suggest you understand the data access of Hibernate and spring integration. Taking a web application as an example, Spring provides opensessioninviewfilter and opensessioninviewinterceptor. We can select a class to implement the same function at will. The only difference between the two methods is that interceptor runs in the spring container and is configured in the context of Web applications, while filter runs before spring and is configured in Web. xml. No matter which one is used, they open the hibernate session when requesting to bind the current session to the current (database) thread. Once bound to a thread, the opened hibernate session can be transparently used in the DAO implementation class. This session keeps the view of the database's median object open for delayed loading. Once the logic view is complete, The Hibernate Session will be closed in the dofilter method of the filter or the posthandle method of interceptor. The following is a configuration example 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>

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>

It is easy to implement the DaO interface of Hibernate to use open sessions. In fact, if you have used the Spring framework to implement your hibernate Dao, you probably don't need to change anything. The convenient hibernatetemplate public Component Changes access to the database into a single disc, 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 ){
Return (integer) gethibernatetemplate (). Save (product );
}

Public void updateproduct (product ){
Gethibernatetemplate (). Update (product );
}
}

 

Use delayed loading in the business logic layer

Even outside the view, the Spring framework uses the AOP interceptor hibernateinterceptor to easily implement delayed loading. This hibernate interceptor transparently intercepts requests for methods configured in the spring application context in the business object, and opens a hibernate session before calling the method, then, close the session after the method is executed. Let's look at a simple example. Suppose 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 CILS
// Dao classes which access
// Data Objects lazily
}
}

 

Through some configuration in the spring application context, we can intercept the method that calls businessobject, and then make its method support delayed loading. Take a look at the following program snippet:

 

<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. After businessobjectimpl is executed, hibernateinterceptor closes the session transparently. The Application Layer Code does not need to understand any persistence layer logic, or implements delayed loading.

Test delayed loading in unit test

Finally, we need to use J-unit to test our delayed loading program. We can easily implement this requirement by rewriting the setup and teardown methods in the testcase class. I prefer to use this convenient abstract class as the base class of all my test classes.

Public abstract class mylazytestcase extends testcase {

Private sessionfactory;
Private session;

Public void setup () throws exception {
Super. Setup ();
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 );
}
}

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.