PDA

View Full Version : Caching the results of a method



Patrick Vanhuyse
Aug 10th, 2005, 03:01 AM
Hi,

I have some business data access and service objects accessing several databases.
These objects are "transactionned" using Spring (TransactionInterceptor, BeanNameAutoProxyCreator).

I want to cache the results of one method of one of the DAO.

How can I do that ?

Here's a summary of my application context :


<?xml version="1.0" encoding="windows-1252"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http&#58;//www.springframework.org/dtd/spring-beans.dtd">

<beans>

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyP laceholderConfigurer">
<property name="location">
<value>/prestation.properties</value>
</property>
</bean>

<bean id="messageSource"
class="org.springframework.context.support.ResourceBundle MessageSource">
<property name="basename">
<value>messages</value>
</property>
</bean>

<!-- Datasource & Transaction -->

<bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBea n"/>

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransaction Manager">
<property name="userTransaction">
<ref local="jotm"/>
</property>
</bean>

<bean id="dossier.dataSource" class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
<property name="transactionManager">
<ref local="jotm"/>
</property>
<property name="driverName">
<value>$&#123;dossier.driverClassName&#125;</value>
</property>
<property name="url">
<value>$&#123;dossier.url&#125;</value>
</property>
<property name="user">
<value>$&#123;dossier.username&#125;</value>
</property>
<property name="password">
<value>$&#123;dossier.password&#125;</value>
</property>
</bean>

<bean id="prestation.dataSource" class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
...
</bean>

<bean id="personnel.dataSource" class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
...
</bean>

<bean id="propagationRequiredAttribute"
class="org.springframework.transaction.interceptor.Defaul tTransactionAttribute">
<property name="propagationBehaviorName">
<value>PROPAGATION_REQUIRED</value>
</property>
</bean>
<bean id="propagationReadOnlyAttribute"
class="org.springframework.transaction.interceptor.Defaul tTransactionAttribute">
<property name="propagationBehaviorName">
<value>PROPAGATION_REQUIRED,readOnly</value>
</property>
</bean>

<bean id="nameTransactionAttributeSource"
class="org.springframework.transaction.interceptor.NameMa tchTransactionAttributeSource">
<property name="nameMap">
<map>
<entry key="ajouter*">
<ref local="propagationRequiredAttribute"/>
</entry>
<entry key="cloturer*">
<ref local="propagationRequiredAttribute"/>
</entry>
<entry key="modifier*">
<ref local="propagationRequiredAttribute"/>
</entry>
<entry key="*">
<ref local="propagationReadOnlyAttribute"/>
</entry>
</map>
</property>
</bean>

<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.Transa ctionInterceptor">
<property name="transactionManager">
<ref local="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<ref local="nameTransactionAttributeSource"/>
</property>
</bean>

<!-- Proxy -->

<bean id="auto" class="org.springframework.aop.framework.autoproxy.BeanNa meAutoProxyCreator">
<property name="interceptorNames">
<list>
<idref local="transactionInterceptor"/>
</list>
</property>
<property name="beanNames">
<list>
<idref local="dossierOAD"/>
<idref local="dossierService"/>
...
</list>
</property>
</bean>

<!-- Business Object -->

<bean id="dossierOAD" class="com.greisch.gestion.prestation.oad.JDBCDossier">
<property name="dataSource">
<ref local="dossier.dataSource"/>
</property>
</bean>
<bean id="dossierService" class="com.greisch.gestion.prestation.DossierServiceImpl">
<property name="dossierOAD">
<ref local="dossierOAD"/>
</property>
</bean>

...

</beans>


Thanks

Colin Yates
Aug 10th, 2005, 04:10 AM
I don't think there is any default spring caching functionality, and I don't think there should be as it is such a domain specific problem ;)

If you are using Hibernate then hibernate can cache.

If you want to write your own, then you can either use interceptors to cache results of a single method, or you can do it the "old" way, wrap your DAO in a cachingDAO and cache in a map, i.e.:



interface MyDAO &#123;
List<MyObject> getResults&#40;final Object someCriteria&#41;;
&#125;

final class HibernateMyDAOImpl extends XYZ implements MyDAO &#123;
public List<MyObject> getResults&#40;final Object someCriteria&#41; &#123;
return getHibernateTemplate etc....
&#125;
&#125;

final class CachingMyDAOImpl implements MyDAO &#123;
private final MyDAO delegate;
private final Cache cache;

public CachingMyDAOImpl&#40;final MyDAO theDelegate, final Cache theCache&#41; &#123;
this.delegate = theDelegate;
this.cache = theCache;
&#125;

public List<MyObject> getResults&#40;final Object someCriteria&#41; &#123;
if &#40;cache.contains&#40;someCriteria&#41;&#41; &#123;
return cache.get&#40;someCriteria&#41;;
&#125; else &#123;
List<MyObject> results = delegate.getResults&#40;someCriteria&#41;;
cache.put&#40;someCriteria, results&#41;;
return results;
&#125;
&#125;
&#125;


HTH.

Patrick Vanhuyse
Aug 10th, 2005, 04:40 AM
There is caching functionality in Spring Modules working like transaction functionality in Spring.
I need some advice to use both at the sime time.

Colin Yates
Aug 10th, 2005, 04:49 AM
Ah, maybe I should read which forum this is before jumping in and offering my 1.5 cents ;) :)

alruiz15
Aug 23rd, 2005, 11:39 AM
Patrick,

If you want, send me your code at alruiz15@yahoo.com and I'll take a look.

Alex.