如果TransactionProxyFactoryBean用于服务层bean,那么是否需要在dao中驱动事务注释?

时间:2011-05-30 08:48:27

标签: java hibernate spring

服务层的接口是:

EMS.java:

public interface EMS extends UserDetailsService {

    public void saveUser(User user);
}

及其实施:

EMSImpl.java:

@Service("emsImpl")
@Transactional(readOnly=true)
public class EMSImpl implements EMS {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    @Qualifier("dao")
    private EMSDao dao;


    @Transactional(readOnly=false)
    public void saveUser(User user) {
        dao.saveUser();
    }
}

dao的界面:

EMSDao.java:

public interface EMSDao {

    public void saveUser(User user);
}

及其实施:

HibernateEMSDao.java

@Repository("EMSDao")
public class HibernateEMSDao extends HibernateDaoSupport implements EMSDao {

    private final Logger logger = LoggerFactory.getLogger(getClass());  

    private SchemaHelper schemaHelper;

    public void setSchemaHelper(SchemaHelper schemaHelper) {
        this.schemaHelper = schemaHelper;
    }

    @Transactional(readOnly=false)
    public synchronized void saveUser(final User user) {        
        Session session = getSessionFactory().getCurrentSession();
        session.merge(user);
        }       

    private void storeUser(User user) {
        getHibernateTemplate().save(user);
    }

    public void createSchema() {        
        try {
            getHibernateTemplate().find("from User user where user.id = 1");
        } catch (Exception e) {
            logger.warn("expected database schema does not exist, will create. Error is: " + e.getMessage());
            schemaHelper.createSchema();
            User admin = new User();
            admin.setUsername("admin");
            admin.setName("Admin");
            admin.setEmail("admin");
            admin.setPassword("21232f297a57a5a743894a0e4a801fc3");
            admin.setRoles(new HashSet<Role>(Arrays.asList(new Role("admin", "ADMINISTRATOR"))));
            logger.info("inserting default admin user into database");
            storeUser(admin);           
            logger.info("schema creation complete");                        
            return;
        }
        logger.info("database schema exists, normal startup");      
    }
}

ems中的appliactionContext.xmlTransactionProxyFactoryBean<tx:annotation-driven />创建。我也在使用<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <bean class="info.ems.config.EMSConfigurer"/> <bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"/> <bean id="ems" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="transactionManager"/> <property name="target"> <bean class="info.ems.EMSImpl" init-method="init"> <property name="dao" ref="dao"/> <property name="passwordEncoder" ref="passwordEncoder"/> <property name="localeList" value="${ems.locales}"/> <property name="releaseVersion" value="${ems.version}"/> <property name="releaseTimestamp" value="${ems.timestamp}"/> <property name="emsHome" value="${ems.home}"/> </bean> </property> <property name="transactionAttributes"> <props> <prop key="store*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="remove*">PROPAGATION_REQUIRED</prop> <prop key="bulkUpdate*">PROPAGATION_REQUIRED</prop> <prop key="*">PROPAGATION_SUPPORTS,readOnly</prop> </props> </property> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <bean id="dataSource" class="info.ems.datasource.DataSourceFactory"> <property name="driverClassName" value="${database.driver}"/> <property name="url" value="${database.url}"/> <property name="username" value="${database.username}"/> <property name="password" value="${database.password}"/> <property name="validationQuery" value="${database.validationQuery}"/> <property name="dataSourceJndiName" value="${database.datasource.jndiname}"/> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation"> <value>/WEB-INF/hibernate.cfg.xml</value> </property> <property name="configurationClass"> <value>org.hibernate.cfg.AnnotationConfiguration</value> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> <prop key="hibernate.current_session_context_class">org.hibernate.context.ThreadLocalSessionContext</prop> </props> </property> </bean> <bean id="dao" class="info.ems.hibernate.HibernateEMSDao" init-method="createSchema"> <property name="hibernateTemplate"> <bean class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"/> </bean> </property> <property name="schemaHelper"> <bean class="info.ems.hibernate.SchemaHelper"> <property name="driverClassName" value="${database.driver}"/> <property name="url" value="${database.url}"/> <property name="username" value="${database.username}"/> <property name="password" value="${database.password}"/> <property name="hibernateDialect" value="${hibernate.dialect}"/> <property name="dataSourceJndiName" value="${database.datasource.jndiname}"/> </bean> </property> </bean> </beans>

完整的applicationContext.xml是:

TransactionProxyFactoryBean

我想知道:

  • 春天处理数据库事务是正确的配置吗?
  • 是否需要将<tx:annotation-driven /><?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <bean class="info.ems.config.EMSConfigurer"/> <bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"/> <bean id="ems" class="info.ems.EMSImpl" init-method="init"> <property name="dao" ref="dao"/> <property name="passwordEncoder" ref="passwordEncoder"/> <property name="localeList" value="${ems.locales}"/> <property name="releaseVersion" value="${ems.version}"/> <property name="releaseTimestamp" value="${ems.timestamp}"/> <property name="emsHome" value="${ems.home}"/> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <bean id="dataSource" class="info.ems.datasource.DataSourceFactory"> <property name="driverClassName" value="${database.driver}"/> <property name="url" value="${database.url}"/> <property name="username" value="${database.username}"/> <property name="password" value="${database.password}"/> <property name="validationQuery" value="${database.validationQuery}"/> <property name="dataSourceJndiName" value="${database.datasource.jndiname}"/> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation"> <value>/WEB-INF/hibernate.cfg.xml</value> </property> <property name="configurationClass"> <value>org.hibernate.cfg.AnnotationConfiguration</value> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> <prop key="hibernate.current_session_context_class">org.hibernate.context.ThreadLocalSessionContext</prop> </props> </property> </bean> <bean id="dao" class="info.ems.hibernate.HibernateEMSDao" init-method="createSchema"> <property name="hibernateTemplate"> <bean class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"/> </bean> </property> <property name="schemaHelper"> <bean class="info.ems.hibernate.SchemaHelper"> <property name="driverClassName" value="${database.driver}"/> <property name="url" value="${database.url}"/> <property name="username" value="${database.username}"/> <property name="password" value="${database.password}"/> <property name="hibernateDialect" value="${hibernate.dialect}"/> <property name="dataSourceJndiName" value="${database.datasource.jndiname}"/> </bean> </property> </bean> </beans> 一起使用?

我可以获得示例的任何信息或网络链接都会非常有用。

谢谢和问候。

编辑:从skaffman获得修改后的appliactionContext.xml建议:

{{1}}

1 个答案:

答案 0 :(得分:3)

  

春天处理数据库事务是否正确?

这是完全有效的,但它令人困惑并重复工作。这可能会生成两层事务代理,但我怀疑它会有什么不同的行为。

正如您所说,您可能不希望同时使用TransactionProxyFactoryBean<tx:annotation-driven />

您的TransactionProxyFactoryBean配置使用外部化方法名称模式来决定哪些方法获取哪些事务语义。这很好,虽然对于当前版本的Spring,通常更容易使用transactionAttributesTransactionProxyFactoryBean属性的注释而不是

鉴于你的配置,我建议摆脱明确的TransactionProxyFactoryBean bean定义(<tx:annotation-driven />将根据需要在幕后创建自己的定义)。将其替换为未修饰的EMSImpl<tx:annotation-driven />将自动生成交易代理。