Source: http://www.cnblogs.com/rongxh7/archive/2010/05/12/1733088.html Respect the original author, visit the original address recently in the study of Hibernate performance optimization encountered a "crawl strategy" , since no detailed studies have been done in the past,
So looking for information everywhere, but no matter from some of the Hibernate books, or others Blog did not find detailed
This article introduces the original crawl strategy described in Hibernate document, which combines lazy loading and other features,
In this oneself in the reference to others on the basis of the study of the original Hibernate four kinds of "crawl strategy";
- connection fetching (join fetching) -Hibernate
SELECT
OUTER JOIN
obtains an associated instance or associated collection of an object by using the (outer join) statement.
- query Fetch (Select fetching) -also sends a
SELECT
statement to fetch the current object's associated real
Body or collection. Unless you explicitly specify prohibit lazy lazy="false"
fetching (lazy fetching), no
The second SELECT statement is executed only if you actually access the associated relationship.
- subquery Fetch (subselect fetching) -also sends a
SELECT
statement fetch in front of the query to
The associated collection of all entity objects (or crawled to). Unless you explicitly specify a lazy="false"
block delay
Crawl (lazy fetching), or only if you actually access the relationship, the second one will be executed.
SELECT statement
- batch fetch (batch fetching) -an optimization scheme for query fetching by specifying a primary key or foreign key
List, Hibernate gets a SELECT
batch of object instances or collections using a single statement
This is the four crawl strategy in the document, and I use a two-way one-to-many example of Customer and Order using four
Crawl strategies to see their differences;
Customer:
View Plaincopy to Clipboardprint?
- public class Customer {
- Private long ID;
- private String name;
- Private set<order> orders;
- Getter/setter slightly
- }
Order:
View Plaincopy to Clipboardprint?
- public class Order {
- Private long ID;
- private String name;
- Private customer customer;
- Getter/setter slightly
- }
The mapping file for Order is immutable and is placed here:
View Plaincopy to Clipboardprint?
-
- <class name= "Order" table= "order_table" >
- <id name= "id" >
- <generator class= "native"/>
- </id>
- <property name= "name" length= "column=" Order_name "/>"
- <many-to-one name= "Customer"
- Class= "Customer"
- lazy= "Proxy"
- Fetch= "SELECT"
- Column= "cus_id"
- Cascade= "Save-update"/>
- </class>
-
connection fetching (join fetching)
Connection fetching, using the connection crawl can be used to query two times (or multiple) of the table of multiple queries to integrate into just
You can do this one query at a time, for example, we're initializing a Customer with a one-to-many relationship
On Order, the Customer table is queried, the customer is found, and then the
Customer.id to the Order table in which the query initializes the Order collection, the completion of this initialization requires
Send at least two SQL statements, and if you use a join query, it will query as needed
Customer.id, the Customer table is connected to the Order table for querying, just one SQL language.
Sentence can be all the data needed to query back;
To use a connection crawl configuration file:
View Plaincopy to Clipboardprint?
-
- <class name= "Customer" table= "customer_table" lazy= "true" >
- <id name= "id" >
- <generator class= "native"/>
- </id>
- <property name= "name" length= "column=" Cus_name "/>"
- <set name= "Orders"
- Inverse= "true"
- Fetch= "Join"//----HERE
- <!--here off lazy loading is to experiment obvious--
- Lazy= "false" >
- <key column= "cus_id"/>
- <one-to-many class= "Order"/>
- </set>
- </class>
-
We use this query statement:
View Plaincopy to Clipboardprint?
- Customer C1 = (customer) session.get (Customer.class, 11l);
- C1.getorders (). Size ();
The SQL statement that Hibernate emits is:
View Plaincopy to Clipboardprint?
- Select
- Customer0_.id as Id0_1_,
- customer0_. Cus_name as Cus2_0_1_,
- Orders1_. cus_id as Cus3_3_,
- Orders1_.id as Id3_,
- Orders1_.id as id1_0_,
- Orders1_. Order_name as order2_1_0_,
- Orders1_. cus_id as Cus3_1_0_
- From
- Customer_table customer0_
- Left OUTER JOIN
- Order_table orders1_
- On customer0_.id=orders1_. cus_id
- where
- Customer0_.id=?
Here, Hibernate uses the left OUTER join connection two tables with an SQL statement to the order collection
to initialize;
query Fetch (Select fetching)
Query fetching, this strategy is the default policy when the collection is crawled, that is, if the collection needs to be initialized, then
A SQL statement will be re-issued to query; This is a collection of default crawl strategies, which we often appear
N+1 query strategy for the second query;
Configuration file:
View Plaincopy to Clipboardprint?
-
- <class name= "Customer" table= "customer_table" lazy= "true" >
- <id name= "id" >
- <generator class= "native"/>
- </id>
- <property name= "name" length= "column=" Cus_name "/>"
- <set name= "Orders"
- Inverse= "true"
- Fetch= "SELECT" >
- <key column= "cus_id"/>
- <one-to-many class= "Order"/>
- </set>
- </class>
-
The query statement does not change, look at the SQL statement that Hibernate sends:
View Plaincopy to Clipboardprint?
- Hibernate:
- Select
- Customer0_.id as id0_0_,
- customer0_. Cus_name as Cus2_0_0_
- From
- Customer_table customer0_
- where
- Customer0_.id=?
- Hibernate:
- Select
- orders0_. cus_id as Cus3_1_,
- Orders0_.id as Id1_,
- Orders0_.id as id1_0_,
- orders0_. Order_name as order2_1_0_,
- orders0_. cus_id as Cus3_1_0_
- From
- Order_table orders0_
- where
- orders0_. Cus_id=?
This is to re-emit an SQL statement that initializes the Orders collection;
subquery Fetch (subselect fetching)
Sub-query Fetch, in addition to send a SELECT statement to crawl in the previous query to (or fetch) all the real
A collection of associations for the body object. This is a bit confusing to understand, for example: If you use Query to find out
4 Customer entities, because lazy loading is turned on, then their Orders are not initialized, then I
Now manually initialize a customer's Orders, at this point because I chose subselect fetching
Policy, Hibernate will associate a collection of entity objects (4 Customer) that were previously queried (in
<set name= "Orders" fetch= "Subselect"/>) use a SELECT statement to crawl at once
Back, this reduces the number of interactions with the database, once the collection of each object is initialized;
[How is he so intelligent? Originally, he was the SQL statement that queried the previous query as
The where subquery of the statement, so the last query to several objects, the set of several objects is initialized this time
Subselect-----Only appears in the <set> collection];
Configuration file:
View Plaincopy to Clipboardprint?
-
- <class name= "Customer" table= "customer_table" lazy= "true" >
- <id name= "id" >
- <generator class= "native"/>
- </id>
- <property name= "name" length= "column=" Cus_name "/>"
- <set name= "Orders"
- Inverse= "true"
- Fetch= "Subselect"
- Lazy= "true" >
- <key column= "cus_id"/>
- <one-to-many class= "Order"/>
- </set>
- </class>
-
The test statement has changed:
View Plaincopy to Clipboardprint?
- List results = Session
- . CreateQuery ("from Customer C, where c.id in (11,14,17,20)")
- . List ();
- The four IDs here are the data that I have ready in my database.
- Customer C0 = (customer) results.get (0);
- C0.getorders (). Size ();
At this point, let's look at what SQL statements Hibernate makes:
View Plaincopy to Clipboardprint?
- Hibernate:
- Select
- Customer0_.id as id0_,
- customer0_. Cus_name as Cus2_0_
- From
- Customer_table customer0_
- where
- Customer0_.id in (
- 11, 14, 17, 20
- )
- Hibernate:
- Select
- orders0_. cus_id as Cus3_1_,
- Orders0_.id as Id1_,
- Orders0_.id as id1_0_,
- orders0_. Order_name as order2_1_0_,
- orders0_. cus_id as Cus3_1_0_
- From
- Order_table orders0_
- where
- orders0_. CUS_ID in (
- Select
- Customer0_.id
- From
- Customer_table customer0_
- where
- Customer0_.id in (
- 11, 14, 17, 20
- )
- )
Is the SQL statement issued in the same form as the name of the crawl strategy? The name of Hibernate is very clear;
batch fetch (batch fetching)
Batch crawl: "The optimization scheme for query fetching, by specifying a primary key or foreign key list, Hibernate uses
A single SELECT statement gets a batch of object instances or collections ", that is, its essence with select fetching is
The same, but one time a select strategy is changed to N-bar batch select query; For example
Son: Or borrow the example of subselect fetching, I have queried 4 Customer entities,
Orders started lazy loading, so I'm now going to manually initialize a Customer's orders property,
This strategy is essentially select fetching, so set:
<set name= "Orders" fetch= "select" batch-size= "3"/> So at this point I initialize
A Customer's orders collection, Hibernate still emits an SQL statement,
However, this SQL is by specifying the list of customer_id foreign keys in the Order table (2), which
When Hibernate Initializes a SQL statement to batch-size the specified number of orders sets;
[How did he do it?] by a primary key or foreign key list, he will 4 Customer based
The batch-size is divided into two groups, a list of three Customer ID values, and the second group has only one,
When initializing the Orders collection is based on these two lists.
Configuration file:
View Plaincopy to Clipboardprint?
- <class name= "Customer" table= "customer_table" lazy= "true" >
- <id name= "id" >
- <generator class= "native"/>
- </id>
- <property name= "name" length= "column=" Cus_name "/>"
- <set name= "Orders"
- Inverse= "true"
- Fetch= "SELECT"
- Lazy= "true"
- Batch-size= "3" >
- <key column= "cus_id"/>
- <one-to-many class= "Order"/>
- </set>
- </class>
In this case, I closed the default lazy load of the collection, which is more conducive to the test results of the code unchanged,
Then look at the SQL statement that Hibernate issued:
View Plaincopy to Clipboardprint?
- Hibernate:
- Select
- Customer0_.id as id0_,
- customer0_. Cus_name as Cus2_0_
- From
- Customer_table customer0_
- where
- Customer0_.id in (
- 11, 14, 17, 20
- )
- Hibernate:
- Select
- orders0_. cus_id as Cus3_1_,
- Orders0_.id as Id1_,
- Orders0_.id as id1_0_,
- orders0_. Order_name as order2_1_0_,
- orders0_. cus_id as Cus3_1_0_
- From
- Order_table orders0_
- where
- orders0_. CUS_ID in (
- ?, ?, ?
- )
- Hibernate:
- Select
- orders0_. cus_id as Cus3_1_,
- Orders0_.id as Id1_,
- Orders0_.id as id1_0_,
- orders0_. Order_name as order2_1_0_,
- orders0_. cus_id as Cus3_1_0_
- From
- Order_table orders0_
- where
- orders0_. Cus_id=?
Originally need four times Select query, because batch-size=3 only used two
was finished;
Summarize:
Well, here are four kinds of crawl strategy explained, to look at the overall, through the example can be seen, these four kinds of crawl
Strategy is not all right, for example, if I need to initialize a separate entity, that
Subselect has no effect on it, because it only needs to query an object, so:
- Join fetching, Select fetching and batch-size can be used as a single entity to crawl into the
Optimize the performance of the line;
- Join fetching, Select fetching, subselect fetching, Batch fetching
Can be used to optimize the performance of the collection;
Note: This can be a bit confusing for a single entity to use Batch-size, in fact <class > is
Having the batch-size crawl strategy; Imagine using a one-to-one relationship? For example, Customer
With Idcard, using HQL to query out 4 customer, we want to initialize 4 customer at once
Idcard What to do, set <class name= "Idcard" batch-size= "4" >, maybe we
The place to set is <one-to-one batch-size> but this property is not provided here, possibly because
If you set a bad understanding of it.
Four different crawl strategies for Hibernate (RPM)