What is hibernate lazy loading? When should I load it with laziness? Why should I load it with laziness ?, Hibernate
Lazy is called delayed loading and delayed loading.
When should I load it with laziness? I can only answer the question: When should I load it with laziness.
Why should we use lazy loading? When the amount of data we want to access is too large, it is obviously inappropriate to use the cache,
Because the memory capacity is limited, in order to reduce the concurrency and reduce the consumption of system resources,
We load data only when needed, and we use lazy loading.
For example, if lazy is set to false, only the po of a department is loaded, the po of all employees will be loaded according to the one-to-many configuration relationship. But in fact, sometimes only department information is needed, and employee information is not required. In this case, loading employee po is a waste of resources. If lazy is set to true, only the employee information of the Department po is loaded when you access the employee information.
In hibernate3.0, lazy has three values: true, false, and proxy. The default value is lazy = "proxy ".
The specific setting depends on your needs. It doesn't mean that the setting is the best.
Suppose that the student object contains a head object
If you are sure you want to use the attributes in the head object when using the student object, you can set to load immediately, because it is set to load immediately, the head of student will be queried at the same time as the student is queried, and hibernate will associate two tables during the query to generate only one SQL statement. If you set delayed loading, one or more SQL statements will be generated: "1" is the statement used to query student, "N" is to query N statements of the head based on N student IDs. In addition, delayed loading is used to execute the query. In this way, the system determines that loading is required, and loading is not required or takes time. The performance is definitely better than loading immediately!
If you need to use the head attribute only when student is used, you can set it to delayed loading, because it is certainly more expensive to query the data of two tables than to query one table.
It depends on your actual needs.
The delayed loading mechanism is proposed to avoid unnecessary performance overhead. The so-called delayed loading means that data loading is performed only when data is actually needed. Hibernate provides delayed loading of object objects and delayed loading of collections, and delayed loading of attributes in Hibernate3.
A. Delayed loading of Object
To use delayed loading for object objects, you must configure the object ing configuration file as follows:
<Hibernate-mapping>
<Class name = "com. neusoft. entity. User" table = "user" lazy = "true">
......
</Class>
</Hibernate-mapping>
You can enable the delayed loading feature of an object by setting the lazy attribute of the class 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 at (1), Hibernate does not initiate data query. If you use some debugging tools to observe the memory snapshot of the user object at this time, you will be surprised to find that, in this case, the returned object may be a User $ EnhancerByCGLIB $ bede8986 object and its attribute is null. How can this problem be solved? The session. load () method returns the proxy class Object of the object. The object type returned here is the proxy class Object of the User object. In Hibernate, CGLIB is used to dynamically construct the proxy class object of a target object, and the proxy class object contains all the attributes and methods of the target object, all attributes are assigned null values. The memory display by the debugger shows the real userobject, which is included in the cglib?calback_0.tar get attribute of the proxy object. When the code runs at (2), the user is called. getName () method. In this case, the CGLIB $ CALBACK_0.getName () method is called through the callback mechanism granted by CGLIB. When the callback is called, hibernatefirst checks whether the cglib1_calback_0.tar get attribute is null, the getName method of the target object is called. If it is null, a database query is initiated to generate an SQL statement similar to this: select * from user where id+'1' to query data, construct the target object, and assign the value to the cgw.calback_0.tar get attribute.
In this way, through an intermediate proxy object, Hibernate achieves object loading delay. Only when a user initiates an action to obtain object attributes can the user initiate a database query operation. Therefore, the delayed loading of objects is completed through the intermediate proxy class, so only session is available. the load () method uses the object to delay loading, because only the session. the load () method returns the proxy class Object of the object class.
B. Delayed loading of Collection types
In the delayed Loading Mechanism of Hibernate, it is of the most significant significance for the application of the set type, because it may greatly improve the performance, so Hibernate has made a lot of efforts, this includes the independent implementation of JDK Collection. In one-to-Multiple Association, the Set defined to hold the associated object is not java. util. set type or its subtype, but net. sf. hibernate. collection. set type. Hibernate implements delayed loading of Set types by using custom collection classes. To use delayed loading for the collection type, you must configure the related section of the object class as follows:
<Hibernate-mapping>
<Class name = "com. neusoft. entity. User" table = "user">
......
<Set name = "addresses" table = "address" lazy = "true" inverse = "true">
<Key column = "user_id"/>
<One-to-define class = "com. neusoft. entity. Arrderss"/>
</Set>
</Class>
</Hibernate-mapping>
Set the lazy attribute of the <set> element to true to enable the delayed loading feature of the set type. See 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 is executed at (1), it does not initiate a query for the associated data to load the associated data. Only when the program runs at (2, the real data read operation starts. At this time, Hibernate searches for object objects that meet the condition based on the Qualified Data Index in the cache.
A new concept-data index is introduced here. What is data index first. In Hibernate, the set type is cached in two parts. First, the IDs of all objects in the set are cached, and then the object IDs are cached, it is the so-called data index. When you look for a data index, if the corresponding data index is not found, a select SQL statement is executed to obtain Qualified Data and construct a collection of Entity objects and data indexes, then return the collection of object objects and include the object objects and data indexes in the cache of Hibernate. On the other hand, if the corresponding data index is found, the id list is retrieved from the data index, and the corresponding entity is searched in the cache based on the id. If it is found, it is returned from the cache, if not, select SQL queries are initiated. Here we can see another problem, which may affect the performance. This is a cache policy of the collection type. If the collection type is as follows:
<Hibernate-mapping>
<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-define class = "com. neusoft. entity. Arrderss"/>
</Set>
</Class>
</Hibernate-mapping>
The <cache usage = "read-only"/> configuration is applied here. If this policy is used to configure the collection type, Hibernate will only cache the data index, instead of caching entity objects in the set. Run the following code in the preceding Configuration:
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 ());
}
Run this code to get 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 can see that when the second query was executed, two queries were performed on the address table. Why? This is because after loading an object for the first time, according to the configuration of the cache policy for the set type, only the collection data index is cached, and the object objects in the set are not cached, therefore, when the object is loaded again for the second time, Hibernate finds the data index of the corresponding object, but it cannot find the corresponding object in the cache according to the data index, therefore, Hibernate initiates two select SQL queries based on the data index. This results in a waste of performance. How can we avoid this situation? You must specify a cache policy for the objects in the collection type to configure the collection type:
<Hibernate-mapping>
<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-define class = "com. neusoft. entity. Arrderss"/>
</Set>
</Class>
</Hibernate-mapping>
At this time, Hibernate caches the objects in the set type and runs the above Code again to get the output similar to the following:
Select * from user where id = '1 ';
Select * from address where user_id = '1 ';
Tianjin
Dalian
Second query ......
Tianjin
Dalian
In this case, no SQL statement is used to query data indexes, because the Entity objects stored in the set type can be directly obtained from the cache.
C. Delayed attribute Loading
In Hibernate3, a new feature-delayed loading of attributes is introduced, which provides a powerful tool for obtaining high-performance queries. When reading a big data object, assume that there is a resume field in the User object. This field is a java. SQL. the Clob type contains the user's resume information. When loading this object, you have to load this field every time, whether or not you really need it or not, in addition, reading such big data objects will bring about great performance overhead. In Hibernate2, the User class is decomposed only through performance-oriented granularity subdivision to solve this problem. However, in Hibernate3, the attribute delay loading mechanism can be used, to obtain the ability to read the data of this field only when we really need to operate on this field. Therefore, we must configure the object class as follows:
<Hibernate-mapping>
<Class name = "com. neusoft. entity. User" table = "user">
......
<Property name = "resume" type = "java. SQL. Clob" column = "resume" lazy = "true"/>
</Class>
</Hibernate-mapping>
You can set true for the lazy attribute of the <property> element to enable delayed loading of the attribute. In Hibernate3, to achieve delayed loading of the attribute, the Class enhancement tool is used to enhance the Class file of the object Class. Through the Enhancement Tool, the logic of the callback mechanism of CGLIB is added to the object Class. Here we can see the delayed loading of the attribute, it is implemented through CGLIB. CGLIB is an open-source project of Apache. This class library can manipulate the bytecode of java classes and dynamically construct class objects that meet the requirements according to the bytecode. Based on the above configuration, 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 at (1), an SQL statement similar to the following will be generated:
Select id, age, name from user where name = 'zx ';
At this time, Hibernate will retrieve all the field data corresponding to the non-delayed loading attribute in the User object. When it is executed at (2), it will generate an SQL statement similar to the following:
Select resume from user where id = '1 ';
In this case, a real read operation is initiated on the resume field data.