Hibernate delay Loading Technology detailed _java

Source: Internet
Author: User
Tags generator sessions

The hibernate delay loading technique is described in this paper. Share to everyone for your reference, specific as follows:

Hibernae delay Loading is a very common technique in which the collection properties of an entity are deferred loaded by default, and the entities associated with entities are deferred loaded by default. Hibernate can reduce the memory overhead of the system through this delay loading, so as to ensure the performance of Hibernate.

The following is the first to dissect the "secret" of Hibernate delay loading.

Deferred loading of collection properties

When Hibernate Initializes a persisted entity from the database, does the collection property of the entity initialize with the persisted class? If the collection attribute contains 100,000 or even millions of records, the ability to crawl all the collection properties while initializing the persisted entity will result in a steep performance drop. It is entirely possible that the system only needs to use some of the records in the persisted class collection properties, not all of the collection properties, so that all collection properties are not necessary to be loaded at once.

For collection properties, it is often recommended that you use a deferred load policy. Deferred loading is when the system needs to use collection properties to load the associated data from the database.

For example, the following person class holds a collection property, the type of the element in the collection property is address, and the code fragment for the person class is as follows:

Listing 1. Person.java

public class person
{
 //Identity attribute
 private Integer ID;
 The person's Name property is
 private String name;
 The age attribute of the person is reserved
 private int age;
 Use set to save collection properties
 Private set<address> addresses = new hashset<address> ();
 The setter and getter methods for each property are omitted below
 ...
}

In order for Hibernate to manage the collection properties of the persisted class, the program provides the following mapping file for the persisted class:

Listing 2. Person.hbm.xml

 <?xml version= "1.0" encoding= "GBK"?> DOCTYPE hibernate-mapping Public "-//hibernate/hibernate mapping DTD 3.0//en" "http://www.hibernate.org/dtd/ Hibernate-mapping-3.0.dtd ">  
 

From the code that maps the file above, you can see that the address class in the collection property of person is just an ordinary POJO. The address class contains detail, zip two properties. Because the address class code is very simple, the code for that class is no longer given.

The code in the <set.../> element of the above mapping file specifies lazy= "true" (lazy= "true" is the default value for <set.../> elements), which specifies that Hibernate will delay loading the collection properties The Address object.

For example, you can load a person entity with ID 1 by using the following code:

Session session = Sf.getcurrentsession ();
Transaction tx = Session.begintransaction ();
Person P = (person) session.get (Person.class, 1); <1>
System.out.println (P.getname ());

The above code simply requires access to the person entity with ID 1 and does not want to access the address object that this person entity is associated with. There are two things at this point:

1. If you do not delay loading, Hibernate immediately crawls the address object associated with the person entity when it loads the corresponding data record.

2. If deferred loading is used, Hibernate only loads the corresponding data records for the person entity.

Obviously, the second approach reduces the interaction with the database and avoids the memory overhead of loading the address entity-which is why Hibernate defaults to enable deferred loading.

The question now is, how exactly is delay loading implemented? Hibernate What is the addresses property value of the person entity when loading the person entity?

To solve this problem, we set a breakpoint at the <1> code and Debug in Eclipse, and you can see the output in Eclipse's Console window as shown in Figure 1:

Figure 1. Lazy load Console output for collection properties

As you can see in Figure 1 output, Hibernate only captures data from the data table corresponding to the person entity, and does not crawl data from the data table corresponding to the Address object, which is deferred loading.

So what is the addresses attribute of the person entity? You can see the results shown in Figure 2 from the Eclipse's Variables window at this point:

Figure 2. Deferred-loaded collection property values

As you can see from the box in Figure 2, this addresses property is not an implementation class that we are familiar with HashSet, TreeSet, but a Persistentset implementation class, a implementation class that Hibernate provides for the Set interface.

The Persistentset collection object does not really crawl the data of the underlying data table, so naturally it cannot initialize the address object in the collection. However, the Persistentset collection holds a session attribute, which is Hibernate sessions, and when the program needs to access the Persistentset collection element, Persistentset takes advantage of the SES Sion property to crawl the actual address object corresponding to the data record.

What about capturing the corresponding data records of those address entities? This is also difficult to persistentset, because the Persistentset collection also has an Owner property, which explains the address object belongs to the person entity, Hibernate will go to find the address corresponding Datasheet foreign key value reference to The data for the person entity.

For example, if we click the addresses row in the window shown in Figure 2, which tells Eclipse to debug and output the Addresses property, and that is to access the Addresses property, you can see the output of SQL in the Console window of Eclipse as follows Sentence

Select
    addresses0_.person_id as person1_0_0_,
    Addresses0_.detail as detail0_,
    Addresses0_.zip as zip0_
from
    person_address addresses0_
where
    addresses0_.person_id=?

This is the Persistentset collection and the SQL statement that captures a particular address record according to the owner attribute. You can now see the output shown in Figure 3 from the Eclipse's Variables window:

Figure 3. Loaded Collection Property values

As you can see from Figure 3, the addresses attribute has been initialized, and the collection contains 2 address objects, which are the two address objects associated with the person entity.

As can be seen from the above, Hibernate for Set property delay loading is the Persistentset implementation class. When deferred loading, the start Persistentset collection does not hold any elements. But Persistentset will hold a Hibernate session, which guarantees that when the program needs to access the collection "immediately" to load the data records and mount the collection elements.

Similar to the Persistentset implementation class, Hibernate also provides implementation classes such as Persistentlist, Persistentmap, Persistentsortedmap, Persistentsortedset, and so on. Their functions are roughly similar to those of Persistentset.

Familiar with Hibernate collection properties readers should remember that Hibernate requires declaring collection properties only with sets, lists, maps, SortedSet, SortedMap, and so on, instead of HashSet, ArrayList, HashMap, TreeSet, TreeMap, and so on, because the Hibernate need to delay loading the collection properties, and Hibernate delay loading is dependent on Persistentset, persistentlist, Persistentmap , Persistentsortedmap, Persistentsortedset-that is to say, the Hibernate layer needs to use its own collection implementation class to complete the deferred loading, so it requires the developer to use a collection interface, Instead of a collection implementation class to declare a collection property.

Hibernate the collection property defaults to deferred loading and, in some special cases, sets the lazy= "false" property for the <set.../>, <list.../>, <map.../>, and so on to cancel the delay load.

Deferred loading of associated entities

By default, Hibernate also uses deferred loading to load the associated entities, whether One-to-many, one-to-one, Many-to-many, Hibernate default is deferred loading.

For an associated entity, you can divide it into two situations:

1. The associated entity is multiple entities (including One-to-many, Many-to-many): At this point the associated entity will be in the form of a collection, and Hibernate will use Persistentset, Persistentlist, Persistentmap, A collection of Persistentsortedmap, Persistentsortedset, and so on to manage deferred-loading entities. This is the scenario described earlier.

2. The associated entity is a single entity (including One-to-one, many-to-many): When Hibernate loads an entity, the deferred associated entity is a dynamically generated proxy object.

When the associated entity is a single entity, that is, the case where the associated entity is mapped using <many-to-one.../> or <one-to-one.../>, these two elements can also specify deferred loading through the lazy property.

The following example maps the address class to a persisted class, at which point the address class becomes an entity class, and the person entity forms a One-to-many two-way association with the address entity. The mapping file code at this point is as follows:

Listing 3. Person.hbm.xml

<?xml version= "1.0" encoding= "GBK"?> <!--specify Hibernate DTD information--> DOCTYPE hibernate-mapping Public "-//hibernate/hibernate mapping DTD 3.0//en" "http://www.hibernate.org/dtd/ Hibernate-mapping-3.0.dtd ">  

The program then loads the person entity with ID 1 by using the following code fragment:

Opens the context-related session sessions Session
= Sf.getcurrentsession ();
Transaction tx = Session.begintransaction ();
Address: Session.get (Address.class, 1); <1>
System.out.println (Address.getdetail ());

To see the processing of its associated entities when Hibernate loads the address entity, we set a breakpoint at the <1> code and Debug in Eclipse, and you can see the following SQL statement output from the Eclipse's Console window:

Select
    address0_.address_id as address1_1_0_,
    Address0_.detail as detail1_0_,
    Address0_.zip as zip1_0_,
    address0_.person_id as person4_1_0_
from
    address_inf address0_
where
    Address0_.address_ Id=?

It is not difficult to see from this SQL statement, Hibernate Load address entity corresponding data table crawl record, not from the person entity corresponding data table crawl record, this is delayed loading play a role.
See the output from Eclipse's Variables window as shown in Figure 4:

Figure 4. Deferred-loaded entities

As you can see clearly in Figure 4, the person entity associated with the address entity is not a person object, but an instance of a Person_$$_javassist_0 class that is dynamically generated by Hibernate using Javassist projects Hibernate-When the associated entity is delayed to load, a dynamic proxy object will be generated using Javassist, which will be responsible for the agent "temporarily not loaded" associated entity.

As long as the application needs to use a "pending" associated entity, the PERSON_$$_JAVASSIST_0 proxy object is responsible for loading the real associated entity and returning the actual associated entity-the most typical proxy pattern.

Click the Person property in the Variables window shown in Figure 4 (that is, forcibly use the person property in debug mode) and see the Eclipse's Console window output the following SQL statement:

Select
    person0_.person_id as person1_0_0_,
    person0_.name as name0_0_,
    Person0_.age as age0_0_
from
    person_inf person0_
where
    person0_.person_id=?

The above SQL statement is the statement to crawl the associated entity "deferred loading." You can see the results of the Variables window output shown in Figure 5:

Figure 5. Loaded entities

Hibernate uses the mode of "deferred loading" to manage the associated entity, in fact, when loading the main entity, it does not really crawl the corresponding data of the associated entity, but only dynamically generates an object as the agent of the associated entity. When an application really needs to use an associated entity, the proxy object is responsible for fetching records from the underlying database and initializing the real associated entity.

In Hibernate delay loading, the client program begins to acquire only a dynamically generated proxy object, while the real entity is delegated to the proxy object to manage-this is the typical proxy pattern.

Agent mode

Agent mode is a very broad design pattern, and when client code needs to invoke an object, the client actually does not care whether to get the object accurately, as long as it can provide an object that provides the function, and then we can return the proxy for that object.

In this design mode, the system provides a proxy object for an object, and the proxy object controls the reference to the source object. An agent is a Java object that represents another Java object to act on. In some cases, the client code does not want to or cannot invoke the callee directly, and the proxy object can mediate between the client and the target object.

To the client, it can not distinguish between proxy object and real object, it does not need to distinguish between proxy object and real object. The client code does not know the real proxy object, the client code is interface-oriented programming, it only holds a proxy object interface.

In summary, as long as the client code cannot or does not want to access the invoked object directly-there are many reasons for this, for example, you need to create a very expensive object, or the object is called on a remote host, or the target object's function is not enough to meet the requirements ... but instead create an extra proxy object to return to the client using the , then this design is the proxy mode.

The following example shows a simple proxy mode, where the program first provides an image interface, representing the interface implemented by the large picture object, which has the following interface code:

Listing 3. Image.java

Public interface Image
{
void Show ();
}

This interface provides an implementation class that simulates a large picture object that the constructor of the implementation class uses the Thread.Sleep () method to pause the 3s. The following is the program code for the Bigimage.

Listing 4. Bigimage.java

Use this bigimage to simulate a large picture public
class Bigimage implements image
{public
bigimage ()
{
try
{
//Program paused 3s mode analog overhead
Thread.Sleep (3000);
System.out.println ("Picture load succeeded ...");
}
catch (Interruptedexception ex)
{
ex.printstacktrace ();
}
}
Implementation of the show () method in Image is public
Void Show ()
{
System.out.println ("Drawing actual large picture");
}


The above program code pauses 3s, which means that creating a Bigimage object requires 3s of time overhead-a program that uses this latency to simulate the overhead of loading this picture. If you do not use proxy mode, the system will generate a 3s delay when you create Bigimage in your program. To avoid this delay, the program provides a proxy object for the Bigimage object, and the proxy class for the Bigimage class is shown below.

Listing 5. Imageproxy.java

The public class Imageproxy implements image
{
//combines an image instance as the object of the proxy as
private image image;
Use abstract entities to initialize proxy object public
imageproxy (image image)
{
this.image = image;
}
/**
* Rewrite the show () method of the Image interface *
This method is used to control access to the proxy object,
* and to be responsible for creating and deleting the proxy object
/public void show
()
{
//Only create the proxy object
if (image = = null)
{
 image = new Bigimage ()
} If you really need to call the Show method of image
image.show ();
}


The Imageproxy proxy class above implements the same show () method as Bigimage, which allows the client code to use the proxy object as a bigimage after it acquires the proxy object.

The control logic is added to the show () method of the Imageproxy class, which controls the actual creation of the represented Bigimage object when the system actually calls the show () of the image. The following program needs to use the Bigimage object, but the program does not return the Bigimage instance directly, but instead returns the Bigimage proxy object first, as shown in the following procedure.

Listing 6. Bigimagetest.java

public class Bigimagetest
{public
static void Main (string[] args)
{
Long start = System.currenttimemillis ();
The program returns an image object that is just the Bigimage proxy object
image image = new Imageproxy (null);
SYSTEM.OUT.PRINTLN ("The system gets the time cost of the Image object:" +
(System.currenttimemillis ()-start));
The program will actually create the proxy object only when the show () method of the image proxy is actually invoked.
image.show ();
}


The above program initializes the image very quickly because the program does not actually create the Bigimage object, just gets the Imageproxy proxy object--until the program calls the Image.show () method, the program needs to actually invoke the show () method of the Bigimage object, the program The Bigimage object is actually created at this time. Run the above program and see the results shown in Figure 6.

Figure 6. Improve performance with Agent mode

See the results shown in Figure 6, the reader should be able to agree: Using proxy mode improves the system performance of getting Image objects. But there may be a reader to ask: The program calls the Imageproxy object's show () method as needed to create the Bigimage object Ah, the system overhead is not really reduced AH? It's just that the system overhead is delayed.

We can answer this question from the following two angles:

The creation of Bigimage is deferred until it is really needed, thus ensuring the fluency of the previous program, and reducing the Bigimage's lifetime in memory, and saving the system's memory overhead from the macro level.

In some cases, perhaps the program will never really call the show () method of the Imageproxy object-meaning that the system does not need to create bigimage objects at all. In this case, the use of proxy mode can significantly improve the performance of the system.

Exactly like this, Hibernate is also through the proxy mode to "postpone" loading the associated entity time, if the program does not need to access the associated entity, the program will not crawl the associated entities, so that both save the system memory overhead, but also can shorten the Hibernate loading entities time.

Summary

Hibernate Delay Loading (lazy load) is essentially the application of proxy mode, in the past years, we often through proxy mode to reduce the system's memory overhead, improve the operational performance of the application. Hibernate leverages this advantage of the proxy model and combines Javassist or cglib to dynamically generate proxy objects, which adds flexibility to the proxy model, Hibernate to a new name for this usage: deferred loading. In any case, the full analysis, understanding of these open source framework implementation can better feel the advantages of the classic design patterns.

I hope this article will help you with Java programming based on the Hibernate framework.

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.