PDA

View Full Version : Caching the results of a method


Patrick Vanhuyse
Aug 10th, 2005, 04: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://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>${dossier.driverClassName}</value>
</property>
<property name="url">
<value>${dossier.url}</value>
</property>
<property name="user">
<value>${dossier.username}</value>
</property>
<property name="password">
<value>${dossier.password}</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, 05: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 {
List<MyObject> getResults(final Object someCriteria);
}

final class HibernateMyDAOImpl extends XYZ implements MyDAO {
public List<MyObject> getResults(final Object someCriteria) {
return getHibernateTemplate etc....
}
}

final class CachingMyDAOImpl implements MyDAO {
private final MyDAO delegate;
private final Cache cache;

public CachingMyDAOImpl(final MyDAO theDelegate, final Cache theCache) {
this.delegate = theDelegate;
this.cache = theCache;
}

public List<MyObject> getResults(final Object someCriteria) {
if (cache.contains(someCriteria)) {
return cache.get(someCriteria);
} else {
List<MyObject> results = delegate.getResults(someCriteria);
cache.put(someCriteria, results);
return results;
}
}
}


HTH.

Patrick Vanhuyse
Aug 10th, 2005, 05: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, 05:49 AM
Ah, maybe I should read which forum this is before jumping in and offering my 1.5 cents ;) :)

alruiz15
Aug 23rd, 2005, 12:39 PM
Patrick,

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

Alex.