Hibernate lazy Loading

Source: Internet
Author: User

Lazy Loading:

The lazy load mechanism is proposed to avoid some unnecessary performance overhead, so-called lazy loading is when the data is really needed to perform the data loading operation. Lazy loading of entity objects and lazy loading of collections are provided in Hibernate, and lazy loading of properties is also provided in Hibernate3. Here we describe the details of these kinds of lazy loading separately.

A, lazy Loading of entity objects:

If you want to use lazy loading on an entity object, you must configure it in the entity's mapping configuration file as follows:

<class name= "Com.neusoft.entity.User" table= "User" lazy= "true" >

......

</class>

Turn on the lazy-load attribute of the entity by setting the class's Lazy property to true. If we run the following code:

User user= (user) Session.load (user.class, "1"); (1)

System.out.println (User.getname ()); (2)

When running to (1), Hibernate does not initiate queries on the data, and if we look at the memory snapshot of the user object at this time through some debugging tools (such as the Debug tool of JBuilder2005), we will be surprised to find that the return is possible at this time user$ enhancerbycglib$ $bede 8986 types of objects, and their properties are null, what's going on? Remember before I spoke of the Session.load () method, which returns the proxy class object of the Entity object, the object type returned here is the proxy class object of the user object. In Hibernate, a proxy class object that dynamically constructs a target object is implemented by using Cglib, and all properties and methods of the target object are included in the proxy class object, and all properties are assigned null. With the memory snapshot shown by the debugger, we can see that the real user object at this point is contained in the Cglib$calback_0.target property of the proxy object, and when the code runs to (2), the User.getname () method is called, At this point the callback mechanism given by Cglib actually calls the Cglib$calback_0.getname () method, and when the method is called, Hibernate first checks whether the Cglib$calback_0.target property is null, if not NULL, The GetName method of the target object is called, and if it is empty, a database query is initiated, generating a SQL statement like this: SELECT * from user where id= ' 1 ', to query the data, construct the target object, and assign it to cglib$calback_0. The target property.

In this way, hibernate implements lazy loading of entities through an intermediary proxy object, and the database query operation is really initiated only when the user actually initiates an action that obtains the attributes of the entity object. So the lazy loading of the entity is done through the intermediate proxy class, so only the Session.load () method takes advantage of entity lazy loading, because only the Session.load () method returns the proxy class object of the entity class.

B, deferred loading of collection types:

In Hibernate's lazy loading mechanism, the significance of the application for the collection type is most significant, as this has the potential to significantly improve performance, and this is a great effort for hibernate, including the standalone implementation of the JDK collection, in a one-to-many association, Defines a set of sets used to hold the associated object, Rather than the Java.util.Set type or its subtypes, but the Net.sf.hibernate.collection.Set type, hibernate implements lazy loading of collection types by using the implementation of a custom collection class. In order to use lazy loading for a collection type, we must configure the associated parts of our entity classes as follows:

<class name= "Com.neusoft.entity.User" table= "User" >

.....

<set name= "Addresses" table= "Address" lazy= "true" inverse= "true" >

<key column= "user_id"/>

<one-to-many class= "Com.neusoft.entity.Arrderss"/>

</set>

</class>

Turn on the lazy-load attribute of the collection type by setting the <set> element's lazily property to true. Let's look at the following code:

User user= (user) Session.load (user.class, "1");

Collection addset=user.getaddresses (); (1)

Iterator It=addset.iterator (); (2)

while (It.hasnext ()) {

Address address= (address) it.next ();

System.out.println (Address.getaddress ());

}

When the program executes to (1), it does not initiate a query to the associated data to load the associated data, and only when it runs to (2), the actual data read operation starts, and Hibernate finds the qualifying entity object based on the data index that matches the criteria in the cache.

Here we introduce a new concept-the data index, which we will first pick up what is the data index. When a collection type is cached in Hibernate, it is cached in two parts, first caching the list of IDs for all entities in the collection, and then caching the entity objects, which are the so-called data indexes. When looking for a data index, if no corresponding data index is found, a select SQL is executed, the data is matched, the entity object collection and the data index are constructed, the collection of entity objects is returned, and the entity object and the data index are included in Hibernate's cache. On the other hand, if the corresponding data index is found, the list of IDs is taken from the data index, and the corresponding entity is found in the cache based on the ID, if it is returned from the cache, if it is not found, the Select SQL query is initiated. Here we see another problem, which can have an impact on performance, which is the cache strategy for the collection type. If we configure the collection type as follows:

<class name= "Com.neusoft.entity.User" table= "User" >

.....

<set name= "Addresses" table= "Address" lazy= "true" inverse= "true" >

<cache usage= "Read-only"/>

<key column= "user_id"/>

<one-to-many class= "Com.neusoft.entity.Arrderss"/>

</set>

</class>

Here we apply the <cache usage= "read-only"/> Configuration, if this policy is used to configure the collection type, hibernate will only cache the data index, not the entity objects in the collection. As configured above we run the following code:

User user= (user) Session.load (user.class, "1");

Collection addset=user.getaddresses ();

Iterator It=addset.iterator ();

while (It.hasnext ()) {

Address address= (address) it.next ();

System.out.println (Address.getaddress ());

}

SYSTEM.OUT.PRINTLN ("Second query ...");

User user2= (user) Session.load (user.class, "1");

Collection it2=user2.getaddresses ();

while (It2.hasnext ()) {

Address address2= (address) it2.next ();

System.out.println (Address2.getaddress ());

}

Running this code will give you output similar to the following:

Select * from user where id= ' 1 ';

Select * FROM address where user_id= ' 1 ';

Tianjin

Dalian

Second query ...

Select * FROM address where id= ' 1 ';

Select * FROM address where id= ' 2 ';

Tianjin

Dalian

We saw that when we executed the query for the second time, we performed two query operations on the Address table. This is because when the entity is loaded for the first time, based on the configuration of the collection type cache policy, the collection data index is cached only, and the entity objects in the collection are not cached, so hibernate finds the data index of the corresponding entity when the entity is reloaded the second time, but according to the data index, Instead of finding the corresponding entity in the cache, hibernate initiated two select SQL query operations based on the data index found, which creates a waste of performance and how can you avoid this situation? We must also specify a cache policy for the entities in the collection type, so we configure the collection type as follows:

<class name= "Com.neusoft.entity.User" table= "User" >

.....

<set name= "Addresses" table= "Address" lazy= "true" inverse= "true" >

<cache usage= "Read-write"/>

<key column= "user_id"/>

<one-to-many class= "Com.neusoft.entity.Arrderss"/>

</set>

</class>

Hibernate will also cache the entities in the collection type, and if you run the above code again based on this configuration, you will get output similar to the following:

Select * from user where id= ' 1 ';

Select * FROM address where user_id= ' 1 ';

Tianjin

Dalian

Second query ...

Tianjin

Dalian

There will be no more SQL statements to query against the data index, because entity objects stored in the collection type can be obtained directly from the cache at this time.

C, attribute lazy loading:

In Hibernate3, a new feature-deferred loading of attributes is introduced, which provides a powerful tool for obtaining high-performance queries. In the front we talked about big data object reads, there is a resume field in the user object, This field is a Java.sql.Clob type, contains the user's CV information, when we load the object, we have to load this field every time, regardless of whether we really need it, and this big data object's reading itself will bring a lot of performance overhead. In Hibernate2, we can only solve this problem by decomposing the user class with the granularity of the surface performance we've talked about (refer to the section), but in Hibernate3, we're able to use the property delay-loading mechanism to To get us to the ability to read this field data only when we really need to manipulate this field, for which we must configure our entity class as follows:

<class name= "Com.neusoft.entity.User" table= "User" >

......

<property name= "Resume" type= "Java.sql.Clob" column= "Resume" lazy= "true"/>

</class>

By setting true for the lazy property of the <property> element to enable lazy loading of the property, the class enhancer is used to harden the classes of the entity classes in Hibernate3 in order to implement deferred loading of the attributes, which is enhanced by the enhancer. The cglib callback mechanism logic is added to the entity class, where we can see the deferred loading of the properties, or the implementation through Cglib. Cglib is an open source project for Apache, which can manipulate the bytecode of Java classes and dynamically construct class objects that meet the requirements based on bytecode. According to the above configuration we run the following code:

String sql= "from user user where user.name= ' ZX '";

Query query=session.createquery (SQL); (1)

List list=query.list ();

for (int i=0;i<list.size (); i++) {

User user= (user) list.get (i);

System.out.println (User.getname ());

System.out.println (User.getresume ()); (2)

}

When executed to (1), a SQL statement similar to the following is generated:

Select id,age,name from user where name= ' ZX ';

Hibernate retrieves the field data for all non-lazy load properties in the user entity, and when it executes to (2), a SQL statement similar to the following is generated:

Select resume from user where id= ' 1 ';

A real read operation is initiated for the Resume field data.

Hibernate lazy Loading

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.