In my Java web application, I have my whole database structure covered by Model classes. It’s really neat, because using those models I can very simply print anything from the database directly in the JSP page. See following example:
<c:if test="${fn:length(author.books) == 0}">The author has no books.</c:if>
<c:forEach items="${author.books}" var="book">
${book.name}
</c:forEach>
Model Author has a method getBooks() which fetches related books from the database and returns a collection of models representing books. The problem is that in the example above the method is called actually twice which results in one redundant query.
I know that I can store the value using <c:set /> but firstly, I would have use that a lot (the example above is quite common in my app) and secondly, it doesn’t always work. For example:
<c:forEach items="${books}" var="book">
${book.author.name}
</c:forEach>
My database unfortunately doesn’t support joins so that for each line I have to run a query to fetch the author from the database (it’s actually pretty fast, because authors are stored in memcache by keys). And let’s say I want to use this loop twice in one page (big menu and small menu or whatever…). So each author is fetched twice from database (or memcache) and that is really not desired.
How do I avoid that? Ideally, the JSP “renderer” should each acquired value store in a temporary cache (just for one request) and next time use this cached value instead of calling the method again. Another way would be to implement this cache directly in the model objects but I don’t know how to do that efficiently without rewriting half of my code. Any ideas?
The biggest problem was with the second described example – I wanted to avoid repetitive fetching of the same entities from the datastore (or memcache). Luckily, all entities are fetched in a completely separated layer. I updated this layer so that now every fetched entity is stored in a HashMap by its key. This HashMap is used as a simple cache – when one entity is demanded more than once, it is fetched only in the first case, after that cached value is used. This HashMap is cleared when the request is finished.
This is more likely a workaround than a real solution I am still interested in other ideas.