More about Criteria

 

In the
earlier note, I have compared the using named query and criteria in general. In
this note, I will talk a bit more about the criteria, as I have realised one
major advantage of criteria that was not mentioned in the earlier note.

 

Here is the scenario.
You need to load a list of publications belong to "Newspaper","Magazine"
and "Newsletter" section and they all should be contained under the “Hongliang.com”
domain. You should also make the metadata information of the publications
available when they are needed.          

 

Would you be
able to find a way to named query to make the metadata information available
while all class are declared as lazy initialised? Right, this is key point for
this note. With the criteria, you can do that easily.

 

public List<Publication> getPublications() {
    //Step 1        
    Criteria pubCriteria = this.getSession().createCriteria(Publication.class)
            .setFetchMode("pubMetadatas", FetchMode.JOIN).setFetchMode("metadata", FetchMode.JOIN)
            .add(Restrictions.in("media", new String[]{"Newspaper","Magazine", "Newsletter" }))
            .addOrder(Order.asc("title"));
 
    //Setp 2
    Criteria domainCriteria = pubCriteria.createCriteria("pubDomains").createCriteria("domain")
            .add(Restrictions.eq("domainName", "hongliang.com"));
 
    //Setp 3
    return domainCriteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();
}

 

(I’d
like to create a DB map for this, but unfortunately the MS Viso crash all the
time) The DAO method can be divided into three steps. The first step creates
the criteria with Publication as root entity. Since we want to have the
metadata information to be accessible via hibernate session, we need to apply some
fetching strategy. In the preceding code, FetchMode.Join has been applied,
which means
Hibernate retrieves
the associated instance or collection in the same
SELECT, using an OUTER JOIN.

You
then need to add the restriction that applied to the criteria, such as “media”
property need to contain values of "Newspaper","Magazine"
and "Newsletter". This has to be added at this step, as pubCriteria
is created with cursor (please correct me, if wrong term used here) pointing to
Publication entity. It is the same reason
Order.asc("title")) need to be
applied here as well.  

 

In
step two, domainCriteria is created as sub criteria of
pubCriteria and its cursor pointing to domain entity. With the same
reason mentioned earlier, the
add(Restrictions.eq("domainName",
"
hongliang.com")) method should be applied here. (If you apply this to
pubCriteria, you will get an exception says something like it can’t find the
property ‘daomainName’ in entity Hongliang.com.Publication)

 

In
step three, though the cursor of domainCriteria is pointing to domain entity,
it still holds the information of the root criteria (
pubCriteria) which includes the join fetch that attached to it. setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY) is used to
get distinct instance of the root entity (Publication)

 

NB. If join fetching
(FetchMode.Join) is not appropriate, you may consider using select fetching.
The definition is here.

Select fetching: a second SELECT is
used to retrieve the associated entity or collection. Unless you explicitly
disable lazy fetching by specifying lazy="false", this
second select will only be executed when you access the association.

 

Reference:

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html#performance-fetching

 

Advertisements
This entry was posted in Hibernate. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s