views:

179

answers:

6

Im looking to create a generic DAO to handle CRUD in my hibernate app. My entities have most associations as LAZY fetching. But I find in order to have hibernate be efficient as possible with the SELECTs I have to create multiple methods on my DAOs. Here's what I mean:

Entity A has two associations. Sometimes I want to retrieve this entity without loading the associations and sometimes I want it fully populated, so I'd put two methods on the DAO:

getWhatever()
getWhateverWithLoadedAssociations()

and I'd have two different queries, one without join fetch, and the other with join fetch. The result is hibernate always does a single select regardless if its LAZY or not, because I know what I want to get up front.

The problem with this is, while saving a SELECT or two, its adding complexity due to the number of methods.

So is this being to extreme? Should I just have getWhatever() and just let hibernate do another select when I need the data for the association, even though I could have saved from not doing that SELECT?

I hope this is not too confusing. I'm trying to figure out the cost of number of SELECTS due to lazy loading, vs. code complexity

thanks

+2  A: 

So your problem is that you may have too many methods? I thinks it's right, because those methods do different things.

If you want to reduce the number and you're using HQL you may add a parameter to the method that says if you want to join fetch the relations:

getWhatever(WhateverFetchMode f)

where f can be a boolean, or an object that returns the HQL fragment of string that gives you that relations to fetch.

public List<MyObject> getList(boolean fetchProp1) {
         return em.createQuery("select r" +
                "from Object as r " +
                fetchProp1 ? "left join fetch r.prop1 " : "")
                .getResultList();
}

or

public List<MyObject> getList(WhateverFetchMode fetchProp1) {
         return em.createQuery("select r" +
                "from Object as r " +
                fetchProp1.toHql()) // This returns the right join fetch
                .getResultList();
}
volothamp
A: 

You can have a common (in a base class) dao method:

public void initialize(Object entity);

Where you call Hibernate.initialize(entity);

Bozho
+2  A: 

I think this might qualify as premature optimization. In other words don't do it unless you know for sure there's a performance problem there.

Just let Hibernate do its lazy fetching for now, and if the app is too slow you can start adding these sort of methods only where they are needed.

Andrei Fierbinteanu
+1  A: 

So is this being to extreme? Should I just have getWhatever() and just let hibernate do another select when I need the data for the association, even though I could have saved from not doing that SELECT?

If you have lazy associations/fetching enabled, then what is the difference if a piece of code that doesn't need the association calls getWhatever() or getWhateverWithLoadedAssociations() ? It should result in the same number of SQL queries.

Examine the possibilities if you have just a single getWhatever() method:

  1. A piece of code doesn't access the associations - no SQL queries to load the associations are triggered
  2. A piece of code does access the associations - SQL queries to load the associations are triggered.

In either case, the association is only loaded when needed.

The purpose of lazy loading is so you don't have to worry about this type of thing - if the code calling the DAO method accesses the association, then it is loaded; if not, it is not.

matt b
I guess the the question is related to the difference of performance when using one single query with joins that fetch the main object and the associations. Which is better than having multiple querys, which is what Hibernate does.
Pau
A: 

In my opinion, yes, you are being extreme.

Unless you are developing a batch procedure with thousends of these queries, there is not much difference between performing one single query and the queries that hibernate does when loading lazyly.

Anyway, if you have confirmed worries about performance in your application, it is not a bad practice what you just proposed.

Pau
+1  A: 

IMHO, I will add some following methods into the generic DAO:

findById(Id id);//lazy load
loadTree(Id id);//load full graph of the entity
load(Id id, String... includePaths);// just load some associations of the entity
Duy Do