9

我确实有一个基于泛型的 DAO 类,它是我项目中所有其他 DAO 类的基础,并包含通用功能:

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) {
        // ...
    }

}

在我的项目中,我使用多个数据源,指向不同的数据库,因此,我确实有多个会话和事务管理器:

<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>

现在我想创建几个 DAO,在不同的数据库上运行:

@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);
    }

}

但问题是,子类Dao没有涵盖所有公共方法,因此不会发生事务管理。@Transactional我能想到的唯一选择是覆盖父类方法,因此它们是在继承类中定义的,因此需要注意@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);
    }

}

但是后来我需要在每个DAO 类中执行此操作,并且代码到处都是相同的......

有没有更好的方法可以在所有类之间共享通用功能并且仍然具有声明式事务管理的所有好处?

4

3 回答 3

2

如果你不介意这个super类也@Transactional一样,你应该把注释放在superDAO 上。如果你介意的话,我建议创建一个扩展类TransactionalDao来扩展主 DAO,@Transactional并且所有应该扩展的 DAO 都@Transactional将扩展它:

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) {
        // ...
    }

}

@Transactional
public class TransactionalDao<E> extends Dao<E>{

    private SessionFactory factory;

    public void setSessionFactory(SessionFactory factory) {
        this.factory = factory;
    }

    public E get(int id) {
        return super.get(id);
    }

    public void save(E entity) {
        super.save(entity);
    }

    public void delete(E entity) {
        super.delete(entity);
    }
}

现在扩展类看起来像这样:

@Repository
@Transactional("manager1") // You'd probably still want the @Transactional for new methods
public class Dao1 extends TransactionalDao<Entity1> {

    @Overrides
    @Autowired
    @Qualifier("factory1")
    public void setSessionFactory(SessionFactory factory) {
        super.setSessionFactory(factory);
    }   
}

这样你只需要做super一次包装。

于 2014-02-12T22:33:28.033 回答
1

您是否尝试过将 @Transaction 放在父 DAO 类的方法上?

public class Dao<E> {

    private SessionFactory factory;

    public void setSessionFactory(SessionFactory factory) {
        this.factory = factory;
    }
    @Transactional(readOnly = true)
    public E get(int id) {
        // ....
    }
    @Transactional
    public void save(E entity) {
        // ...
    }
    @Transactional
    public void delete(E entity) {
        // ...
    }
}

这样,当您在 DAO1 上调用 save 时,它​​将从子类中获取类级别的 @Transaction(它将指定要使用的 TX 管理器),然后从父类的 save 方法中获取方法级别的 @Transactional。

于 2014-02-12T22:25:41.147 回答
-2

您应该使用基于 AOP 的事务管理@Transactional,而不是到处添加注释,例如 -

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
</bean>

  <tx:advice id="txAdvice" transaction-manager="txManager">  
  <tx:attributes>  
    <tx:method name="get*" read-only="true"/>  
    <tx:method name="*"/>
  </tx:attributes>
  </tx:advice>

在服务层使用事务是一种很好的做法。

于 2013-01-04T07:52:06.450 回答