Settings of lazy and fetch in hibernate associations

Source: Internet
Author: User

The lazy and fetch settings in the relationship between hibernate will affect the SQL statement operations when querying data. The fetch settings have a higher priority than the lazy settings, the lazy attribute configured on the class label does not affect the associated object. (The version used in this example is hibernate3)

In this example, a master table is set to masttb and a sub-table is set to detailtb.

For the fetch of the primary table, 'join', 'select', and 'subselect' can be used (the default value is select ):

Join: an external join is queried once.

Select: 1 + N select statements. The first query is the primary table, and the nth query is the subtable record corresponding to the nth primary table record.

Subselect: Use Id in (...) (If the primary table returns a single record, there is no difference between Subselect and select. If the primary table returns multiple records, subtable queries are performed by ID in ). for details, see Example 4.

Lazy can take 'true', 'extra ', and 'false' (true is the default value ):

True: the default value. It indicates that a query statement is issued to load the data of element in the collection only when the element object in the collection is obtained by calling this set.
False: cancel the delayed loading feature, that is, when the object is loaded, the second query statement is issued to load the data of the associated set.
Extra: A clever latency loading policy, that is, when calling methods such as size/contains of a set, Hibernate does not load the data of the entire set, instead, a "smart" SQL statement is issued to obtain the required values. The query statement is issued to load the data of all objects only when the data of these collection element objects is actually needed.
For example, check the size of the Set:

The following SQL statement will be issued

Select
Count (dtid)
From
Detailtb
Where
Mtid =?

1. Perform the findbyid query test on the master table. When fetch is set to join, whether lazy is true or false, all associated data is retrieved in the form of a left Outer Join sub-table of the master table. the SQL statement is as follows:

Select
Masttb0 _. Mid as mid1_1 _,
Masttb0 _. mastinfo as mastinfo1_1 _,
Detailtbs1 _. mtid as mtid3 _,
Detailtbs1 _. dtid as dtid3 _,
Detailtbs1 _. dtid as dtid2_0 _,
Detailtbs1 _. mtid as mtid2_0 _,
Detailtbs1 _. detailinfo as detailinfo2_0 _
From
Masttb masttb0 _
Left Outer Join
Detailtb detailtbs1 _
On masttb0 _. Mid = detailtbs1 _. mtid
Where
Masttb0 _. Mid =?

2. Perform a findbyid query test on the master table. When fetch is set to select and lazy is true, Hibernate first uses an SQL statement to check the data of the master table, then, when the sub-table data is retrieved (when the set iterator is accessed), the foreign key of the sub-table is used as the condition and the data of the sub-table is obtained using an SQL statement.
The Java code is as follows:
Tx = sessionfactory. getcurrentsession (). begintransaction ();
Masttbhome = new masttbhome ();

Masttb = masttbhome. findbyid (New bigdecimal (1 ));
System. Out. println ("before getting detai set ");

Set set = masttb. getdetailtbs ();

System. Out. println ("after getting detai set ");
Iterator itr = set. iterator ();
System. Out. println ("after getting detai set iterator ");
While (itr. hasnext ()){
Detailtb = (detailtb) itr. Next ();
System. Out. println ("after getting detai Info" + detailtb. getdtid ());
}

TX. Commit ();
The running result is as follows:
Hibernate:
Select
Masttb0 _. Mid as mid1_0 _,
Masttb0 _. mastinfo as mastinfo1_0 _
From
Masttb masttb0 _
Where
Masttb0 _. Mid =?
Before getting detai set
After getting detai set
Hibernate:
Select
Detailtbs0 _. mtid as mtid1 _,
Detailtbs0 _. dtid as dtid1 _,
Detailtbs0 _. dtid as dtid2_0 _,
Detailtbs0 _. mtid as mtid2_0 _,
Detailtbs0 _. detailinfo as detailinfo2_0 _
From
Detailtb detailtbs0 _
Where
Detailtbs0 _. mtid =?
After getting detai set iterator
After getting detai Info 2
After getting detai info 1

3. Perform a findbyid query test on the master table. When fetch is set to select and lazy is false, Hibernate first uses an SQL statement to check the data of the master table, then, take the foreign key of the sub-table as the condition and use an SQL statement to retrieve the data of the sub-table.
The code in example 2 above will print:
Hibernate:
Select
Masttb0 _. Mid as mid1_0 _,
Masttb0 _. mastinfo as mastinfo1_0 _
From
Masttb masttb0 _
Where
Masttb0 _. Mid =?
Hibernate:
Select
Detailtbs0 _. mtid as mtid1 _,
Detailtbs0 _. dtid as dtid1 _,
Detailtbs0 _. dtid as dtid2_0 _,
Detailtbs0 _. mtid as mtid2_0 _,
Detailtbs0 _. detailinfo as detailinfo2_0 _
From
Detailtb detailtbs0 _
Where
Detailtbs0 _. mtid =?
Before getting detai set
After getting detai set
After getting detai set iterator
After getting detai Info 2
After getting detai info 1

* If lazy is set to true and fetch is set to select, an exception occurs when the session is closed and the value in the set is accessed.
Org. hibernate. lazyinitializationexception: failed to lazily initialize a collection of Role: COM. Test. HB. masttb. detailtbs, no session or session was closed

 

4. perform multiple record queries on the master table. When fetch is set to Subselect and lazy is true, Hibernate first uses an SQL statement to check the data in the master table, then, use the SQL statement ID in to retrieve the data of the sub-table.

Java code:

Tx = sessionfactory. getcurrentsession (). begintransaction ();

List mstlist = sessionfactory. getcurrentsession (). createquery ("From Com. Test. HB. masttb where ID in (1, 2)"). List ();

// The hql below has the same effect as the preceding hql

// List mstlist = sessionfactory. getcurrentsession (). createquery ("From Com. Test. HB. masttb where ID <3"). List ();
For (iterator iter = mstlist. iterator (); ITER. hasnext ();){
Masttb = (masttb) ITER. Next ();
System. Out. println ("masttb. getmastinfo =" + masttb. getmastinfo ());
Set set = masttb. getdetailtbs ();
System. Out. println (set. Size ());
If (set! = NULL &&! Set. isempty ()){
For (iterator itr = set. iterator (); itr. hasnext ();){
Detailtb = (detailtb) itr. Next ();
System. Out. println ("detailtb. Name =" + detailtb. getdetailinfo ());
}
}
}

TX. Commit ();

Running result:

Hibernate:
Select
Masttb0 _. Mid as mid1 _,
Masttb0 _. mastinfo as mastinfo1 _
From
Masttb masttb0 _
Where
Masttb0 _. Mid in (
1, 2
)
Masttb. getmastinfo = mastinfo
Hibernate:
Select
Detailtbs0 _. mtid as mtid1 _,
Detailtbs0 _. dtid as dtid1 _,
Detailtbs0 _. dtid as dtid2_0 _,
Detailtbs0 _. mtid as mtid2_0 _,
Detailtbs0 _. detailinfo as detailinfo2_0 _
From
Detailtb detailtbs0 _
Where
Detailtbs0 _. mtid in (
Select
Masttb0 _. Mid
From
Masttb masttb0 _
Where
Masttb0 _. Mid in (
1, 2
)
)
Number in detail table: 2
Detailtb. Name = AAAA
Detailtb. Name = detailinfo2
Masttb. getmastinfo = aaa
Number in detail table: 1
Detailtb. Name = adfasdfa

If fetch = select and lazy = true, the running result is 1 + 2 SQL statements:

Hibernate:
Select
Masttb0 _. Mid as mid1 _,
Masttb0 _. mastinfo as mastinfo1 _
From
Masttb masttb0 _
Where
Masttb0 _. Mid in (
1, 2
)
Masttb. getmastinfo = mastinfo
Hibernate:
Select
Detailtbs0 _. mtid as mtid1 _,
Detailtbs0 _. dtid as dtid1 _,
Detailtbs0 _. dtid as dtid2_0 _,
Detailtbs0 _. mtid as mtid2_0 _,
Detailtbs0 _. detailinfo as detailinfo2_0 _
From
Detailtb detailtbs0 _
Where
Detailtbs0 _. mtid =?
Number in detail table: 2
Detailtb. Name = AAAA
Detailtb. Name = detailinfo2
Masttb. getmastinfo = aaa
Hibernate:
Select
Detailtbs0 _. mtid as mtid1 _,
Detailtbs0 _. dtid as dtid1 _,
Detailtbs0 _. dtid as dtid2_0 _,
Detailtbs0 _. mtid as mtid2_0 _,
Detailtbs0 _. detailinfo as detailinfo2_0 _
From
Detailtb detailtbs0 _
Where
Detailtbs0 _. mtid =?
Number in detail table: 1
Detailtb. Name = adfasdfa

 

For the fetch of a sub-table, 'join' and 'select' can be used (the default value is select ),

Join: an external join is queried once.

Select: Two select statements.

Lazy can take 'proxy', 'no-proxy', and 'false' (proxy is the default value ).

False: cancel the delayed loading feature, that is, when the object is loaded, the second query statement is sent to load the data of the associated primary table.

The meaning of proxy is similar to that of lazy in the master table. when accessing the master table object, Hibernate returns a proxy object. At this time, no database value is accessed.
No-proxy has the same effect as proxy, but the proxy object is not dynamic. It is created during compilation and requires specific compilation (requires build-time bytecode Instrumentation ).

5. Test the findbyid query on the child table. When fetch is set to join, whether lazy is false or proxy, all the associated data is retrieved once when the left outer table of the sub-table is connected to the master table. the SQL statement is as follows:
Select
Detailtb0 _. dtid as dtid2_1 _,
Detailtb0 _. mtid as mtid2_1 _,
Detailtb0 _. detailinfo as detailinfo2_1 _,
Masttb1 _. Mid as mid1_0 _,
Masttb1 _. mastinfo as mastinfo1_0 _
From
Detailtb detailtb0 _
Left Outer Join
Masttb masttb1 _
On detailtb0 _. mtid = masttb1 _. Mid
Where
Detailtb0 _. dtid =?

6. Test the findbyid query on the sub-table. When fetch is set to select, lazy is false. hibernate first uses an SQL statement to check the data of the sub-table, then, the foreign key of the sub-table is immediately used as the primary key value of the master table to query the data of the master table.
Hibernate:
Select
Detailtb0 _. dtid as dtid2_0 _,
Detailtb0 _. mtid as mtid2_0 _,
Detailtb0 _. detailinfo as detailinfo2_0 _
From
Detailtb detailtb0 _
Where
Detailtb0 _. dtid =?
Hibernate:
Select
Masttb0 _. Mid as mid1_0 _,
Masttb0 _. mastinfo as mastinfo1_0 _
From
Masttb masttb0 _
Where
Masttb0 _. Mid =?
Before accessing mast table data

7. Test the findbyid query on the sub-table. When fetch is set to select, lazy is the proxy. hibernate first uses an SQL statement to check the data of the sub-table, then, when you need to access the data of the primary table, use the foreign key of the sub-table as the value of the primary key of the primary table, and use an SQL statement to retrieve the data of the primary table. (and if the value you want to access is the primary key value, because the primary key value is exactly the foreign key value of the sub-table, the primary key attribute of the proxy object already has a value, hibernate does not send SQL statements to query databases)
Hibernate:
Select
Detailtb0 _. dtid as dtid2_0 _,
Detailtb0 _. mtid as mtid2_0 _,
Detailtb0 _. detailinfo as detailinfo2_0 _
From
Detailtb detailtb0 _
Where
Detailtb0 _. dtid =?
Before accessing mast table data (SQL statements are not issued before data is accessed)

Hibernate:
Select
Masttb0 _. Mid as mid1_0 _,
Masttb0 _. mastinfo as mastinfo1_0 _
From
Masttb masttb0 _
Where
Masttb0 _. Mid =?

* Similarly, if lazy is set to proxy and fetch is set to select, an exception occurs when the value in the primary table is accessed after the session is closed (only the primary key value is accessed without exception ).
Org. hibernate. lazyinitializationexception: cocould not initialize proxy-No session

 

 

Note the following:
When both the Sub-table and the master table are set to lazy = "false", the data of the sub-table is queried first. This is the SQL statement used to query the database. According to the Select Settings, SQL is different. after querying the data of the primary table, an SQL statement is issued (the condition is the foreign key of the sub-table = the primary key of the primary table) to query the sub-table (this step is redundant ).

The following code:

Detailtbhome = new detailtbhome ();
Detailtb = detailtbhome. findbyid (New bigdecimal (1 ));

SQL:

Hibernate:
Select
Detailtb0 _. dtid as dtid2_0 _,
Detailtb0 _. mtid as mtid2_0 _,
Detailtb0 _. detailinfo as detailinfo2_0 _
From
Detailtb detailtb0 _
Where
Detailtb0 _. dtid =?
Hibernate:
Select
Masttb0 _. Mid as mid1_0 _,
Masttb0 _. mastinfo as mastinfo1_0 _
From
Masttb masttb0 _
Where
Masttb0 _. Mid =?
Hibernate: // because the lazy of the primary table is false, the following SQL statement is sent to query the subtable.

Select
Detailtbs0 _. mtid as mtid1 _,
Detailtbs0 _. dtid as dtid1 _,
Detailtbs0 _. dtid as dtid2_0 _,
Detailtbs0 _. mtid as mtid2_0 _,
Detailtbs0 _. detailinfo as detailinfo2_0 _
From
Detailtb detailtbs0 _
Where
Detailtbs0 _. mtid =?
After findbyid detailinfo1

 

Through the above example, we can find that the best practice is to use the default settings of lazy and fetch of hibernate, so that the associated records will not be retrieved during hibernate get and load. if you need to retrieve the associated records, use criteria for query and use criteria. setfetchmode queries associated records in the code.
You can also control the SQL statement or hql statement passed in the query.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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.