views:

200

answers:

5
+2  Q: 

Java DAO caching

I'm developing a medium Java app, and i'm facing a small problem due to my lack of experience.

I've a custom DAO, which gets "Article" objects from the Database. I've the Article class, and the DAO has a method called getArticle(int id), this method returns an Article. The Article has a Category object, and I'm using lazy loading.

So, when I request for an article's category (Article a = new Article(); a.getCategory();) the Article class gets the Category from the DAO and then returns it.

I'm now thinking to cache it, so when I request multiple times to an article's category, the database is only queried one time.

My question is: where should I put that cache? I can put it on the Article class (in the DTO), or I can put it on the DAO class.

What do you say?

+7  A: 

Have you considered using Hibernate?

Sualeh Fatehi
Exactly, no need to reinvent the wheel. It might be a fun exercise to implement some sort of cache on your own, but if you just want to get the application working, go with Hibernate. It has facilities to handle caching for you automatically, and you will pick up some valuable experience with an industry standard ORM framework while you're at it.
William Brendel
If you propose a pre-made solution, I think it's good to also explain briefly how it works w.r.t to the original question, in this case, the caching of data. See my answer.
ewernli
+2  A: 

The purpose of the DAO is to abstract away the persistence mechanism. Since 'where' the category comes from (DB, file on disk, network socket, Cache) is part of that persistence mechanism, the DAO should 'hide' it from the object consuming it.

Affe
A: 

It depends on whether your Article the only class to directly access the DAO or not.

Personally I would implement the caching in Article for the simple fact that not everyone using the DAO will want caching. Also from a point of view of having one Class do one thing and one thing only, since you already have the lazy loading in Article it wouldnt make sense to then move part of the way loading happens in the DAO

hhafez
+3  A: 

Consider using Hibernate or even the more simpler form of it (JPA)

Mohammed
+4  A: 

My question is: where should I put that cache? I can put it on the Article class (in the DTO), or I can put it on the DAO class.

As the others mentioned, it sounds indeed a bit like re-inventing the wheel. But let's consider both cases anyway, so that you will get better understanding of how ORM works.

If you store the category in the article, the same category will be loaded again and again if accessed by different articles.

getCategory() {
   if( category == null ) { category = <load from DAO> }
   return category;
}

If you store it in the DAO, then all articles with the same category will benefit the cache, but you need to take care to update the cache as well when the category is changed.

saveCategory( Category c ) {
     cache.put( c.id, c ); 
     <save in database>
}

Problem with this approach is that (1) the cache may grow large over time, and (2) that external update in the database will never be reflected if you don't have a timeout mechanism or a way to clear the cache.

Actually, ORM such as Hibernate have three levels of caching:

  1. The entity itself. When the category is lazy loaded, it's stored in the article entity for subsequent direct access.
  2. The first-level cache. This is the cache of the current session/transaction. The same entity won't be loaded twice but fetched from the cache.
  3. The 2nd-level cache. This is a cache across all sessions/transactions. It corresponds to the option of caching the value in the DAO. 2nd level cache is sometimes trickier because of the reasons I mentioned above.

Hope you see better the shortcomings/benefits of each type of cache. For more information, look in popular ORM documentation. Theses issues are common and well documented.

ewernli
Thanks man, this is a really architect answer. I know Hibernate, i use JPA actually, but i've used Hibernate. I'm trying to do it at my own, like a hobbie. I think i'll use entity and 2nd-level cache, with some observers and timeouts. Thanks again brother!
santiagobasulto