Fetching strategy: How does Hibernate obtain the associated Object Policy when an application needs to navigate between associations (in the Hibernate object graph. The capture policy can be declared in the metadata of the O/R ing, or in a specific HQL or condition Query (Criteria Query.
Configuring the capture policy can directly affect the query efficiency of the get () and load () Methods of the Session.
Hibernate3 defines the following capture policies:
* Join fetching-Hibernate uses the outer join statement in the SELECT statement to obtain the associated instance or set of objects.
* Select fetching-another SELECT statement is sent to capture the associated entities or sets of the current object. Unless you explicitly specify lazy = "false" to prohibit lazy fetching, the second select statement will be executed only when you actually access the association.
* Subselect fetching-also sends a SELECT statement to capture the association set of all object objects previously queried (or crawled. Unless you explicitly specify lazy = "false" to prohibit lazy fetching, the second select statement will be executed only when you actually access the association.
* Batch fetching-an optimization solution for query capturing. by specifying a primary key or foreign key list, Hibernate uses a single SELECT statement to obtain a Batch of object instances or sets.
Hibernate crawling policies differentiate the following situations:
1. Immediate fetching, capture immediately-when the host is loaded, the Association, set, or attribute is immediately captured.
2. Lazy collection fetching: delays collection capturing-the collection is not crawled until the application performs an operation on the collection. (This is the default action for the set .)
3. "Extra-lazy" collection fetching, "Extra-lazy" collection capturing-for each element in the collection class, it is not necessary to access the database. Unless absolutely necessary, Hibernate will not try to capture the entire set into the memory (applicable to very large sets ).
4. Proxy fetching, Proxy capture-for the association of returned single values, it is captured only when a method is called rather than the get operation on its keywords.
5. "No-proxy" fetching, non-proxy crawling-for the association of returned single values, it is captured when the instance variable is accessed. Compared with the preceding proxy crawling, this method is not so "delayed" (even if only the access identifier is used, it will also lead to associated crawling) but more transparent, because for the application, proxy is no longer seen. This method requires bytecode enhancement during compilation, so it is rarely used.
6. Lazy attribute fetching: delayed attribute loading-for associations of attributes or returned single values, the instance variables are crawled when they are accessed. This method is rarely necessary because it requires enhanced bytecode during compilation.
There are two orthogonal concepts: when the association is captured and how it is crawled (what SQL statements will be used ). Don't confuse them! We use crawling to improve performance. We use latency to define some contracts. We know which data can be used for a managed instance of a specific class.
1. Association of Operation delay Loading
By default, Hibernate 3 uses latency select capture for the collection and latency proxy capture for the association of returned single values. For almost all applications, the vast majority of their associations are effective.
Note: If you set hibernate. default_batch_fetch_size, Hibernate will take batch capture Optimization Measures for delayed loading (this optimization may also be enabled at a more refined level ).
However, you must understand a problem caused by latency capture. Calling a delayed set outside the context of an opened Hibernate session may cause an accident. For example:
Java code collection code
<Span style = "font-size: large;"> s = sessions. openSession ();
Transaction tx = s. beginTransaction ();
User u = (User) s. createQuery ("from User u where u. name =: userName"). setString ("userName", userName). uniqueResult ();
Map permissions = u. getPermissions ();
Tx. commit ();
S. close ();
Integer accessLevel = (Integer) permissions. get ("accounts"); // Error! </Span>
After the Session is closed, the permessions set will be uninstantiated and no longer available, so it cannot be loaded normally. Hibernate does not support delayed instantiation of unmanaged objects. The modification method here is to move the code for reading permissions data before tx. commit.
In addition, by specifying lazy = "false" for the association ing, we can also use a non-delayed set or association. However, for the vast majority of sets, it is recommended to use the latency method to capture data. If too many non-delayed associations are defined in your object model, Hibernate eventually needs to load the entire database into the memory in almost every transaction!
On the other hand, in some special transactions, we often need to use connection crawling (which is non-delayed in itself) to replace query crawling. Next we will soon understand how to customize the crawling policy in Hibernate. In Hibernate3, the mechanism for selecting which capture policy is consistent with that of selecting single-value association or set Association.
2. Adjust the capture policy (Tuning fetch strategies)
Query crawling (default) is extremely fragile in the case of N + 1 queries, so we may require the definition of using connection crawling in the ing document:
Java code collection code
<Span style = "font-size: large;"> <set name = "permissions" fetch = "join">
<Key column = "userId"/>
<One-to-define class = "Permission"/>
</Set>
<Role-to-one name = "mother" class = "Cat" fetch = "join"/> </span>
The capture policy defined in the ing document will affect the following list entries: get data through the get () or load () method. Data is implicitly obtained only when the association is navigated.
Conditional query: HQL query captured by subselect is used.
No matter which crawling policy you use, class diagrams defined as non-delay will be guaranteed to be loaded into the memory. Note that this may mean that a series of queries are followed after an HQL query.
Generally, we do not use ing documents to customize crawling policies. More importantly, keep its default value, and then use the left join fetch of HQL to reload it in a specific transaction. This will notify Hibernate to use external join in the first query to directly obtain the associated data. In the conditional query API, call the setFetchMode (FetchMode. JOIN) statement.
You may like to change the data capture policy in the get () or load () Statements by using conditional queries only. For example:
Java code collection code
<Span style = "font-size: large;"> User user = (User) session. createCriteria (User. class ).
SetFetchMode ("permissions", FetchMode. JOIN ).
Add (Restrictions. idEq (userId). uniqueResult (); </span>
(This is the equivalent of "fetch plan" in Hibernate for other ORM solutions .) A completely different method to avoid N + 1 queries is to use second-level cache.
Sample configuration (mainly in two cases ):
1) Capture on a single-ended Association (<sequence-to-one> or <one-to-sequence>)
You can add the fetch attribute to the single-ended associated ing element. The fetch attribute has two optional values.
A). select: as the default value, its policy is to send a select statement to capture the data of the associated object of the current object when the party needs to use the data of the associated object. That is, delayed loading.
B). join: it uses the same select statement to connect Li AI to obtain the data of the object and the data of the object associated with it. In this case, the delayed loading of the associated object fails.
The following is a configuration example of fetch = join on a single-ended join.
Java code collection code
<Span style = "font-size: large;"> <? Xml version = "1.0" encoding = "UTF-8"?>
<! DOCTYPE hibernate-mapping PUBLIC
"-// Hibernate/Hibernate Mapping DTD 3.0 // EN"
Http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd>
<Hibernate-mapping>
<Class name = "com. javacrazyer. domain. Product" table = "product">
<Id name = "id">
<Generator class = "native"/>
</Id>
<Version name = "version"/>
<Property name = "name"/>
<Property name = "unitCost" column = "unit_cost"/>
<Property name = "pubTime" column = "pub_time"/>
<! -- Ing multiple-to-one -->
<Subtitle-to-one name = "cate" column = "cate_id" fetch = "join"/>
</Class>
</Hibernate-mapping> </span>
When loading the data of an entity product in an application, the associated Category entity is also loaded using the inner connection, which is similar to the following SQL statement:
Add SQL code to favorites
<Span style = "font-size: large;"> select tab1.xx, tab1.yy, tab2.aa, tab2.cc
From product tab1
Inner join category tab2
On tab1.cate _ id = tab2.id
Where product_id =? </Span>
2) Capture policies on set attributes
You can add the fetch attribute to the ing element of the Set property. It has three optional values.
A). select: as the default value, its policy is that when the party needs to use the data of the associated set, it separately sends a select statement to capture the associated set of the current object, that is, delayed loading.
B). join: In the same select statement, join is used to obtain the correlated set of the object. In this case, the lazy on the correlated set becomes invalid.
C). subselect: In addition, send an integrated query statement (or subquery statement) to capture the association set of all object objects previously queried. This policy also applies to HQL queries.
The following is an example of fetch = subselect on the set property.
Java code collection code
<Span style = "font-size: large;"> <? Xml version = "1.0" encoding = "UTF-8"?>
<! DOCTYPE hibernate-mapping PUBLIC
"-// Hibernate/Hibernate Mapping DTD 3.0 // EN"
Http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd>
<Hibernate-mapping>
<Class name = "com. javacrazyer. domain. Category" table = "category" batch-size = "10">
<Id name = "id">
<Generator class = "native"/>
</Id>
<Version name = "version"/>
<Property name = "name"/>
<Property name = "description"/>
<! -- Ing set Attributes -->
<Bag name = "productList" inverse = "true" fetch = "subselect">
<Key column = "cate_id"/>
<! -- Ing one to multiple -->
<One-to-learn class = "com. javacrazyer. domain. Product"/>
</Bag>
</Class>
</Hibernate-mapping> </span>
When you use the get () or load () method to load a Category object data, it delays loading the associated Product set attributes. when you really need to use the data in the Product set attributes, then, an SQL statement is sent to capture data. When multiple CategoryShiite data are loaded using HQL statements, the associated Product set attributes are loaded with delayed loading, when you really need to use the data of the Product set attribute, a query statement is sent to capture the corresponding data.
Batch Capture:
(1) In Hibernate, for association capturing, you can define the number of data captured each time, load data into memory in batches, and reduce the number of interactions with the database. In the application, you can define the default number of associated crawlers in the workshop. In
<Hibernate-configuration>
<Session-factory>
<Property name-"default_batch_fetch_size"> 2 </property>
</Session-factory>
</Hibernate-configuration>
(2) In the ing definition file, the attribute batch-size may be used in the element class to specify the number of batch captures for the persistence class. Similarly, if you want to use the specified batch in the set, you can use the batch-size attribute in the set Element set (list, bag, etc. If the default batch capture configuration is used in the same step, and a specific capture quantity is configured for the persistence class or set, the specific configuration of the class or set will overwrite the default batch capture attribute in the configuration file.
<Hibernate-mapping package = "com">
<Class name = "Classes">
<Id name = "id">
<Generator class = "native"> </generator>
</Id>
<Property name = "name"/>
<Set name = "students" inverse = "true" batch-size = "3">
<Key column = "classesid"/>
<One-to-learn class = "Student"/>
</Set>
</Class>
</Hibernate-mapping>
Author: ERDP Technical Architecture"