I do have a generics-based DAO class, which is base for all other DAO classes in my project and contains common functionality:
public class Dao<E> {
private SessionFactory factory;
public void setSessionFactory(SessionFactory factory) {
this.factory = factory;
}
public E get(int id) {
// ....
}
public void save(E entity) {
// ...
}
public void delete(E entity) {
// ...
}
}
In my project I am using multiple datasources, pointing to different databases, therefore, I do have multiple session and transaction managers:
<bean id="factory1" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="source1" />
</bean>
<bean id="manager1" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="factory1" />
</bean>
<bean id="factory2" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="source2" />
</bean>
<bean id="manager2" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="factory2" />
</bean>
Now I want to create couple of DAOs, operating on different databases:
@Repository
@Transactional("manager1")
public class Dao1 extends Dao<Entity1> {
@Overrides
@Autowired
@Qualifier("factory1")
public void setSessionFactory(SessionFactory factory) {
super.setSessionFactory(factory);
}
}
@Repository
@Transactional("manager2")
public class Dao1 extends Dao<Entity2> {
@Overrides
@Autowired
@Qualifier("factory2")
public void setSessionFactory(SessionFactory factory) {
super.setSessionFactory(factory);
}
}
but the problem is, that all public methods from Dao
aren't covered by @Transactional
from a child classes, so no transaction management occurs. The only option what I can think of is to override the parent class methods, so they are defined in inherited classes and therefore are taken care by @Transactional
:
@Repository
@Transactional("manager1")
public class Dao1 extends Dao<Entity1> {
@Overrides
@Autowired
@Qualifier("factory1")
public void setSessionFactory(SessionFactory factory) {
super.setSessionFactory(factory);
}
@Overrides
public Entity1 get(int id) {
return super.get(id);
}
@Overrides
public void save(Entity1 entity) {
super.save(entity);
}
@Overrides
public void delete(Entity1 entity) {
super.delete(entity);
}
}
But then I would need to do this in every DAO class, and code would be everywhere the same…
Is there a better way how to share common functionality across all classes and still have all benefits of declarative transaction management?
Best Answer
In case you don't mind the
super
class would be@Transactional
as well, you should put the annotation on thesuper
DAO. In case you do mind, I suggest creating one extending classTransactionalDao
that will extend the main DAO and be@Transactional
and all the DAOs that should be@Transactional
as well will extend it:And now the extending class would look like that:
This way you only have to do this
super
wrapping thing only once.