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

Java 如果TransactionProxyFactoryBean用于服务层bean,那么是否需要dao中驱动的事务注释?,java,hibernate,spring,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 logg

服务层的接口为:

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();
    }
}
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");      
    }
}
dao的接口:

EMSDao.java:

public interface EMSDao {

    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();
    }
}
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");      
    }
}
我想知道:

  • 它是spring处理数据库事务的正确配置吗
  • 是否需要将
    TransactionProxyFactoryBean
    一起使用
任何信息或网页链接,我可以得到的例子将非常有用

谢谢和问候

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

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

/WEB-INF/hibernate.cfg.xml
org.hibernate.cfg.AnnotationConfiguration
${hibernate.dial}
${hibernate.show_sql}
org.hibernate.context.ThreadLocalSessionContext
它是spring处理数据库事务的正确配置吗

这是完全正确的,但它是混乱的,重复的工作。这可能会生成两层事务代理,尽管我怀疑其行为是否会有所不同

正如您所说,您可能不想同时使用
TransactionProxyFactoryBean

您的
TransactionProxyFactoryBean
config正在使用外部化方法名模式来决定哪些方法获得哪些事务语义。这很好,尽管在Spring的当前版本中,通常更容易使用注释而不是
TransactionProxyFactoryBean
上的
transactionAttributes
属性


根据您的配置,我建议去掉显式的
TransactionProxyFactoryBean
bean定义(
将根据需要在幕后创建自己的定义)。将其替换为未修饰的
emsiml
将自动生成事务代理。

我根据您的建议添加了修改后的appliactionContext.xml,并对其进行了测试,它正在工作。这就是你的建议吗?我没有对其他java代码做任何更改,即EMS.java、emsiml.java、EMSDao.java、HibernateEMSDao.java。