Contenu connexe
Similaire à 12 global fetching strategies (20)
Plus de thirumuru2012 (9)
12 global fetching strategies
- 2. Lazy Default Fetch Plan
Professional Open Source™
Hibernate defaults to a lazy fetching strategy for all entities and
collections.
Item item = (Item) session.load(Item.class, new Long(123));
load() will return a proxy and the sql that loads an Item isn’t executed .
A proxy is a placeholder that triggers the loading of the real object
when it’s accessed for the first time .
Item item = (Item) session.load(Item.class, new Long(123));
item.getId();
item.getDescription(); // Initialize the proxy
As long as you access only the database identifier property, no
initialization of the proxy is necessary.
© JBoss, Inc. 2003, 2004. 2
- 3. What is the need of a proxy ?
Professional Open Source™
A proxy is useful if you need the Item only to create a reference, for
example:
Item item = (Item) session.load(Item.class, new Long(123));
User user = (User) session.load(User.class, new Long(1234));
Bid newBid = new Bid("99.99");
newBid.setItem(item);
newBid.setBidder(user);
session.save(newBid);
© JBoss, Inc. 2003, 2004. 3
- 4. After initializing the proxy ….
Professional Open Source™
A Fully initialized Item proxy Associated entity objects and
collections are not loaded right
away; the proxies carry the
identifier values only.
Collections also aren’t loaded right
away, but we use the term
collection wrapper to describe this
kind of placeholder.
Internally, Hibernate has a set of
smart collections that can initialize
themselves on demand. Hibernate
replaces your collections with these;
that is why you should use collection
interfaces only in your domain
model.
By default, Hibernate creates placeholders for all associations and
collections, and only retrieves value-typed properties and components
right away.
© JBoss, Inc. 2003, 2004. 4
- 5. When are collections initialized
Professional Open Source™
a collection is initialized if you start iterating through its elements or if
you call any of the collection-management operations, such as size()
and contains().
Hibernate provides an additional setting that is mostly useful for large
collections; they can be mapped as extra lazy.
The collection wrapper is now
smarter than before.
The collection is no longer
initialized if you call size(),
contains(), or isEmpty()—the
database is queried
to retrieve the necessary
information.
© JBoss, Inc. 2003, 2004. 5
- 6. Disabling proxy generation
Professional Open Source™
You can disable proxy generation for a particular entity class with the
lazy="false" attribute
<class name="User“ table="USERS“ lazy="false">
...
</class>
Disabling proxy generation on a global level is often too coarse-
grained.
Usually, you only want to disable the lazy loading behavior of a
particular entity association or collection to define a fine-grained fetch
plan.
© JBoss, Inc. 2003, 2004. 6
- 7. Eager loading of associations and collections
Professional Open Source™
Let’s assume that you always require the seller of an Item. In
Hibernate XML mapping metadata you’d map the association from
Item to User as lazy="false":
For eager loading collections …..
After eager loading of
bids , seller and successful
Bid
© JBoss, Inc. 2003, 2004. 7
- 8. Selecting a fetching Strategy
Professional Open Source™
Item item = (Item) session.get(Item.class, new Long(123));
You didn’t configure any association or collection to be nonlazy, and
that proxies can be generated for all associations. Hence, this
operation results in the following SQL SELECT:
select item.* from ITEM item where item.ITEM_ID = ?
If you access any proxied association or uninitialized collection, a
second SELECT is executed to retrieve the data on demand.
By selecting a good fetching strategy, we have to reduce the
number of on-demand SELECTS
© JBoss, Inc. 2003, 2004. 8
- 9. Prefetching data in batches
Professional Open Source™
If every entity association and collection is fetched only on demand,
many additional SQL SELECT statements may be necessary to
complete a particular procedure .
List allItems = session.createQuery("from Item").list();
processSeller( (Item)allItems.get(0) );
processSeller( (Item)allItems.get(1) );
processSeller( (Item)allItems.get(2) );
You see one SQL SELECT to retrieve all the Item objects, and an
additional SELECT for every seller of an Item as soon as you process
it. All associated User objects are proxies.
select items...
select u.* from USERS u where u.USER_ID = ?
select u.* from USERS u where u.USER_ID = ?
select u.* from USERS u where u.USER_ID = ?
© JBoss, Inc. 2003, 2004. 9
- 10. Prefetching data in batches
Professional Open Source™
Batch fetching is often called a blind-guess optimization .
You make a guess and apply a batch-size fetching strategy to your
User class mapping:
<class name="User“ table="USERS“ batch-size="10">
...
</class>
You’re telling Hibernate to prefetch up to 10 uninitialized proxies in a
single SQL SELECT, if one proxy must be initialized. The resulting
SQL for the earlier query and procedure may now look as follows:
select items...
select u.* from USERS u where u.USER_ID in (?, ?, ?,?... 10 times)
© JBoss, Inc. 2003, 2004. 10
- 11. Batch Fetching for collections
Professional Open Source™
Batch fetching is also available for collections:
<set name="bids“ inverse="true“ batch-size="10">
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>
</set>
© JBoss, Inc. 2003, 2004. 11
- 12. Prefetching collections with subselects
Professional Open Source™
<set name="bids“ inverse="true“ fetch="subselect">
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>
</set>
Hibernate now initializes all bids collections for all loaded Item
objects, as soon as you force the initialization of one bids collection.
It does that by rerunning the first initial query (slightly modified) in a
subselect:
select i.* from ITEM i
select b.* from BID b
where b.ITEM_ID in (select i.ITEM_ID from ITEM i)
© JBoss, Inc. 2003, 2004. 12
- 13. Eager fetching with joins
Professional Open Source™
<class name="Item" table="ITEM">
…
<many-to-one name="seller“ class="User“ column="SELLER_ID"
update="false“ fetch="join"/>
</class>
Hibernate now loads both an Item and its seller in a single SQL
statement. For example:
Item item = (Item) session.get(Item.class, new Long(123));
This operation triggers the following SQL SELECT:
select i.*, u.*
from ITEM i
left outer join USERS u on i.SELLER_ID = u.USER_ID
where i.ITEM_ID = ?
If you only enable eager fetching with lazy="false", you see an
immediate second SELECT. With fetch="join", you get the seller
loaded in the same single SELECT.
© JBoss, Inc. 2003, 2004. 13
- 14. Eager fetching collections
Professional Open Source™
You can also set the eager join fetching strategy on a collection:
<class name="Item" table="ITEM">
...
<set name="bids“ inverse="true“ fetch="join">
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>
</set>
</class>
Following is the query executed when item is loaded :
select i.*, b.*
from ITEM i
left outer join BID b on i.ITEM_ID = b.ITEM_ID
© JBoss, Inc. 2003, 2004. 14
- 15. Controlling the maximum number of joined entity associations
Professional Open Source™
Let’s assume that Item has a successfulBid association, that Bid
has a bidder, and that User has a shippingAddress. If all these
associations are mapped with fetch="join", how many tables are
joined and how much data is retrieved when you load an Item?
The number of tables joined in this case depends on the global
hibernate. max_fetch_depth configuration property.
Reasonable settings are small, usually between 1 and 5.
You may even disable join fetching for many-to-one and one-to-one
associations by setting the property to 0!
© JBoss, Inc. 2003, 2004. 15
- 16. Outer joins for a table-per-subclass hierarchy
Professional Open Source™
select
b1.BILLING_DETAILS_ID, b1.OWNER,b1.USER_ID,b2.NUMBER,
b2.EXP_MONTH,b2.EXP_YEAR,b3.ACCOUNT,b3.BANKNAME,b3.SWIFT,
case
when b2.CREDIT_CARD_ID is not null then 1
when b3.BANK_ACCOUNT_ID is not null then 2
when b1.BILLING_DETAILS_ID is not null then 0
end as clazz
from
BILLING_DETAILS b1
left outer join CREDIT_CARD b2
on b1.BILLING_DETAILS_ID = b2.CREDIT_CARD_ID
left outer join BANK_ACCOUNT b3
on b1.BILLING_DETAILS_ID = b3.BANK_ACCOUNT_ID
It joins three tables . Many dbms limit the maximum number of tables that can be
combined with an OUTER JOIN.
© JBoss, Inc. 2003, 2004. 16
- 17. Switching to additional selects
Professional Open Source™
The only way to enable this fetching strategy is to refactor the mapping slightly, as a mix of table-
per-hierarchy (with a discriminator column) and table-per-subclass with the <join> mapping:
<class name="BillingDetails“ table="BILLING_DETAILS“ abstract="true">
<id name="id“ column="BILLING_DETAILS_ID“ .../>
<discriminator column="BILLING_DETAILS_TYPE“ type="string"/>
...
<subclass name="CreditCard" discriminator-value="CC">
<join table="CREDIT_CARD" fetch="select">
<key column="CREDIT_CARD_ID"/>
...
</join>
</subclass>
<subclass name="BankAccount" discriminator-value="BA">
<join table="BANK_ACCOUNT" fetch="join">
<key column="BANK_ACCOUNT_ID"/>
...
</join>
</subclass>
</class>
© JBoss, Inc. 2003, 2004. 17
- 18. Professional Open Source™
select
b1.BILLING_DETAILS_ID, b1.OWNER, b1.USER_ID,
b2.ACCOUNT,b2.BANKNAME,b2.SWIFT,b1.BILLING_DETAILS_TYPE as clazz
from
BILLING_DETAILS b1
left outer join
BANK_ACCOUNT b2
on b1.BILLING_DETAILS_ID = b2.BANK_ACCOUNT_ID
select cc.NUMBER, cc.EXP_MONTH, cc.EXP_YEAR
from CREDIT_CARD cc where cc.CREDIT_CARD_ID = ?
select cc.NUMBER, cc.EXP_MONTH, cc.EXP_YEAR
from CREDIT_CARD cc where cc.CREDIT_CARD_ID = ?
Fetch=“select” tells hibernate to fire an immediate select
© JBoss, Inc. 2003, 2004. 18
- 19. The n+1 selects problem
Professional Open Source™
This code produces n+1 selects
Instead of n+1 selects, u will see n/10 +1
selects
© JBoss, Inc. 2003, 2004. 19
- 20. Professional Open Source™
With a subselect-based prefetch, you can reduce
the number of selects to exactly two
This will turn off lazy loading which is not advised
If needed, u can enable dynamic fetching strategy to join as follows :
© JBoss, Inc. 2003, 2004. 20
- 21. Forcing proxy and collection initialization
Professional Open Source™
Hibernate.initialize( item.getSeller() );
© JBoss, Inc. 2003, 2004. 21