Monday, August 20, 2012

Hibernate – Fetching Strategies Examples

Hibernate has few fetching strategies to optimize the Hibernate generated select statement, so that it can be as efficient as possible. The fetching strategy is declared in the mapping relationship to define how Hibernate fetch its related collections and entities.

Fetching Strategies

There are four fetching strategies
  • fetch-”join” = Disable the lazy loading, always load all the collections and entities.
  • fetch-”select” (default) = Lazy load all the collections and entities.
  • batch-size=”N” = Fetching up to ‘N’ collections or entities, *Not record*.
  • fetch-”subselect” = Group its collection into a sub select statement.

For detail explanation, you can check on the Hibernate documentation.

Fetching Strategies Examples

Here’s a “one-to-many relationship” example for the fetching strategies demonstration. A stock is belong to many stock daily records.

Lets explore how fetch strategies affect the Hibernate generated SQL statement.

Fetch=”Select” Or @Fetch(FetchMode.SELECT)

This is the default fetching strategy. it enabled the lazy loading of all it’s related collections.

Output:
Hibernate: 
    select ...from mkyong.stock
    where stock0_.STOCK_ID=?
 
Hibernate: 
    select ...from mkyong.stock_daily_record
    where stockdaily0_.STOCK_ID=?

Hibernate generated two select statements
1. Select statement to retrieve the Stock records -session.get(Stock.class, 114)
2. Select its related collections – sets.iterator()

Fetch=”Join” Or @Fetch(FetchMode.JOIN)

The “join” fetching strategy will disabled the lazy loading of all it’s related collections.

Output:
Hibernate: 
    select ...
    from
        mkyong.stock stock0_ 
    left outer join
        mkyong.stock_daily_record stockdaily1_ 
            on stock0_.STOCK_ID=stockdaily1_.STOCK_ID 
    where
        stock0_.STOCK_ID=?

Hibernate generated only one select statement, it retrieve all its related collections when the Stock is initialized. -session.get(Stock.class, 114)
1. Select statement to retrieve the Stock records and outer join its related collections.

Batch-Size=”10″ Or @BatchSize(Size = 10)

This ‘batch size’ fetching strategy is always misunderstanding by many Hibernate developers.

What is your expected result, is this per-fetch 10 records from collection? See the Output
Hibernate: 
    select ...from mkyong.stock
    where stock0_.STOCK_ID=?
 
Hibernate: 
    select ...from mkyong.stock_daily_record
    where stockdaily0_.STOCK_ID=?

The batch-size did nothing here, it is not how batch-size work. See this statement.
The batch-size fetching strategy is not define how many records inside in the collections are loaded. Instead, it defines how many collections should be loaded.
— Repeat N times until you remember this statement —

You want to print out all the stock records and its related stock daily records (collections) one by one.
No batch-size fetching strategy
Output:
Hibernate: 
    select ...
    from mkyong.stock stock0_
 
Hibernate: 
    select ...
    from mkyong.stock_daily_record stockdaily0_ 
    where stockdaily0_.STOCK_ID=?
 
Hibernate: 
    select ...
    from mkyong.stock_daily_record stockdaily0_ 
    where stockdaily0_.STOCK_ID=?
 
Keep repeat the select statements....depend how many stock records in your table.

If you have 20 stock records in the database, the Hibernate’s default fetching strategies will generate 20+1 select statements and hit the database.

1. Select statement to retrieve all the Stock records.
2. Select its related collection
3. Select its related collection
4. Select its related collection
….
21. Select its related collection
The generated queries are not efficient and caused a serious performance issue.


Enabled the batch-size=’10′ fetching strategy
Let see another example with batch-size=’10′ is enabled.
Output:
Hibernate: 
    select ...
    from mkyong.stock stock0_
 
Hibernate: 
    select ...
    from mkyong.stock_daily_record stockdaily0_ 
    where
        stockdaily0_.STOCK_ID in (
            ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
        )

Now, Hibernate will per-fetch the collections, with a select *in* statement. If you have 20 stock records, it will generate 3 select statements.
1. Select statement to retrieve all the Stock records.
2. Select In statement to per-fetch its related collections (10 collections a time)
3. Select In statement to per-fetch its related collections (next 10 collections a time)

With batch-size enabled, it simplify the select statements from 21 select statements to 3 select statements.

Fetch=”Subselect” Or @Fetch(FetchMode.SUBSELECT)

This fetching strategy is enable all its related collection in a sub select statement.

Output:
Hibernate: 
    select ...
    from mkyong.stock stock0_
 
Hibernate: 
    select ...
    from
        mkyong.stock_daily_record stockdaily0_ 
    where
        stockdaily0_.STOCK_ID in (
            select
                stock0_.STOCK_ID 
            from
                mkyong.stock stock0_
        )

With “subselect” enabled, it will create two select statements.
1. Select statement to retrieve all the Stock records.
2. Select all its related collections in a sub select query.



Conclusion The fetching strategies are highly flexible and a very important tweak to optimize the Hibernate query, but if you used it in a wrong place, it will be a total disaster (You're screwed dude!).


Monday, August 6, 2012

Delegated vs. Federated ID

It is important to understand that there are two different kind of single-sign-on solutions: delegated and federated. All the recent comparisons between OpenID and Facebook Connect failed to appreciate this fundamental difference. Facebook Connect is a delegated authentication service, while OpenID is a federated authentication service. They might offer very similar features, but they are very different.

A delegated solution means that one site is simply outsourcing its authentication needs to another pre-selected site. If your site uses Facebook Connect, you are delegating your authentication facilities to Facebook. Visitors to your site cannot use any other accounts, only accounts from the vendors you have pre-selected.

A federated solution means that visitors to your site can use any account they have, as long as it is compatible. It makes no difference to the site which account is being used, as long as it can interoperate. At its core, OpenID is a federated solution because its most important feature is the ability to use any OpenID account with any OpenID-enabled service.

Delegated authentication has a few drawbacks with respect to federated authentication. First, delegated authentication is inherently less secure than federated authentication. Even if encrypted, delegated authentication still sends the username and password (possibly even your network password) over the internet.

More Information...