Four different crawl strategies for Hibernate

Source: Internet
Author: User
Tags what sql

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?

    1. public class Customer {
    2. Private long ID;
    3. private String name;
    4. Private set<order> orders;
    5. Getter/setter slightly
    6. }

Order:

View Plaincopy to Clipboardprint?

    1. public class Order {
    2. Private long ID;
    3. private String name;
    4. Private customer customer;
    5. Getter/setter slightly
    6. }

The mapping file for Order is immutable and is placed here:

View Plaincopy to Clipboardprint?

    1. <class name= "Order" table= "order_table" >
    2. <id name= "id" >
    3. <generator class= "native"/>
    4. </id>
    5. <property name= "name" length= "column=" Order_name "/>"
    6. <many-to-one name= "Customer"
    7. Class= "Customer"
    8. lazy= "Proxy"
    9. Fetch= "SELECT"
    10. Column= "cus_id"
    11. Cascade= "Save-update"/>
    12. </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?

    1. <class name= "Customer" table= "customer_table" lazy= "true" >
    2. <id name= "id" >
    3. <generator class= "native"/>
    4. </id>
    5. <property name= "name" length= "column=" Cus_name "/>"
    6. <set name= "Orders"
    7. Inverse= "true"
    8. Fetch= "Join"//----HERE
    9. <!--here off lazy loading is to experiment obvious--
    10. Lazy= "false" >
    11. <key column= "cus_id"/>
    12. <one-to-many class= "Order"/>
    13. </set>
    14. </class>

We use this query statement:

View Plaincopy to Clipboardprint?

    1. Customer C1 = (customer) session.get (Customer.class, 11l);
    2. C1.getorders (). Size ();

The SQL statement that Hibernate emits is:

View Plaincopy to Clipboardprint?

    1. Select
    2. Customer0_.id as Id0_1_,
    3. customer0_. Cus_name as Cus2_0_1_,
    4. Orders1_. cus_id as Cus3_3_,
    5. Orders1_.id as Id3_,
    6. Orders1_.id as id1_0_,
    7. Orders1_. Order_name as order2_1_0_,
    8. Orders1_. cus_id as Cus3_1_0_
    9. From
    10. Customer_table customer0_
    11. Left OUTER JOIN
    12. Order_table orders1_
    13. On customer0_.id=orders1_. cus_id
    14. where
    15. 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?

    1. <class name= "Customer" table= "customer_table" lazy= "true" >
    2. <id name= "id" >
    3. <generator class= "native"/>
    4. </id>
    5. <property name= "name" length= "column=" Cus_name "/>"
    6. <set name= "Orders"
    7. Inverse= "true"
    8. Fetch= "SELECT" >
    9. <key column= "cus_id"/>
    10. <one-to-many class= "Order"/>
    11. </set>
    12. </class>

The query statement does not change, look at the SQL statement that Hibernate sends:

View Plaincopy to Clipboardprint?

  1. Hibernate:
  2. Select
  3. Customer0_.id as id0_0_,
  4. customer0_. Cus_name as Cus2_0_0_
  5. From
  6. Customer_table customer0_
  7. where
  8. Customer0_.id=?
  9. Hibernate:
  10. Select
  11. orders0_. cus_id as Cus3_1_,
  12. Orders0_.id as Id1_,
  13. Orders0_.id as id1_0_,
  14. orders0_. Order_name as order2_1_0_,
  15. orders0_. cus_id as Cus3_1_0_
  16. From
  17. Order_table orders0_
  18. where
  19. 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?

    1. <class name= "Customer" table= "customer_table" lazy= "true" >
    2. <id name= "id" >
    3. <generator class= "native"/>
    4. </id>
    5. <property name= "name" length= "column=" Cus_name "/>"
    6. <set name= "Orders"
    7. Inverse= "true"
    8. Fetch= "Subselect"
    9. Lazy= "true" >
    10. <key column= "cus_id"/>
    11. <one-to-many class= "Order"/>
    12. </set>
    13. </class>

The test statement has changed:

View Plaincopy to Clipboardprint?

    1. List results = Session
    2. . CreateQuery ("from Customer C, where c.id in (11,14,17,20)")
    3. . List ();
    4. The four IDs here are the data that I have ready in my database.
    5. Customer C0 = (customer) results.get (0);
    6. C0.getorders (). Size ();

At this point, let's look at what SQL statements Hibernate makes:

View Plaincopy to Clipboardprint?

  1. Hibernate:
  2. Select
  3. Customer0_.id as id0_,
  4. customer0_. Cus_name as Cus2_0_
  5. From
  6. Customer_table customer0_
  7. where
  8. Customer0_.id in (
  9. 11, 14, 17, 20
  10. )
  11. Hibernate:
  12. Select
  13. orders0_. cus_id as Cus3_1_,
  14. Orders0_.id as Id1_,
  15. Orders0_.id as id1_0_,
  16. orders0_. Order_name as order2_1_0_,
  17. orders0_. cus_id as Cus3_1_0_
  18. From
  19. Order_table orders0_
  20. where
  21. orders0_. CUS_ID in (
  22. Select
  23. Customer0_.id
  24. From
  25. Customer_table customer0_
  26. where
  27. Customer0_.id in (
  28. 11, 14, 17, 20
  29. )
  30. )

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?

  1. <class name= "Customer" table= "customer_table" lazy= "true" >
  2. <id name= "id" >
  3. <generator class= "native"/>
  4. </id>
  5. <property name= "name" length= "column=" Cus_name "/>"
  6. <set name= "Orders"
  7. Inverse= "true"
  8. Fetch= "SELECT"
  9. Lazy= "true"
  10. Batch-size= "3" >
  11. <key column= "cus_id"/>
  12. <one-to-many class= "Order"/>
  13. </set>
  14. </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?

  1. Hibernate:
  2. Select
  3. Customer0_.id as id0_,
  4. customer0_. Cus_name as Cus2_0_
  5. From
  6. Customer_table customer0_
  7. where
  8. Customer0_.id in (
  9. 11, 14, 17, 20
  10. )
  11. Hibernate:
  12. Select
  13. orders0_. cus_id as Cus3_1_,
  14. Orders0_.id as Id1_,
  15. Orders0_.id as id1_0_,
  16. orders0_. Order_name as order2_1_0_,
  17. orders0_. cus_id as Cus3_1_0_
  18. From
  19. Order_table orders0_
  20. where
  21. orders0_. CUS_ID in (
  22. ?, ?, ?
  23. )
  24. Hibernate:
  25. Select
  26. orders0_. cus_id as Cus3_1_,
  27. Orders0_.id as Id1_,
  28. Orders0_.id as id1_0_,
  29. orders0_. Order_name as order2_1_0_,
  30. orders0_. cus_id as Cus3_1_0_
  31. From
  32. Order_table orders0_
  33. where
  34. 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:

    1. Join fetching, Select fetching and batch-size can be used as a single entity to crawl into the
      Optimize the performance of the line;
    2. 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)

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.