0

我正在使用具有以下配置的 Spring 3.1 和 Hibernate 3.0 来测试声明性事务,但看不到回滚语句。

在这里我注意到,每次它都打开一个新会话。我想这可能会导致问题。

我的配置/代码有什么问题吗..?

{
    Log
    ----
    09:40:54.909 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0'
    09:40:54.914 [main] DEBUG o.s.t.i.NameMatchTransactionAttributeSource - Adding transactional method [save*] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-SNTransException]
    09:40:54.914 [main] DEBUG o.s.t.i.NameMatchTransactionAttributeSource - Adding transactional method [get*] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly]
    09:40:54.914 [main] DEBUG o.s.t.i.NameMatchTransactionAttributeSource - Adding transactional method [*] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT]

    09:40:54.936 [main] DEBUG o.s.o.hibernate3.SessionFactoryUtils - Opening Hibernate Session
    09:40:54.960 [main] DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 13750710549
    09:40:54.978 [main] DEBUG o.h.e.def.AbstractSaveEventListener - executing identity-insert immediately
    09:40:54.979 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
    09:40:54.979 [main] DEBUG org.hibernate.jdbc.ConnectionManager - opening JDBC connection
    09:40:54.979 [main] DEBUG o.s.j.d.DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/test]
    09:40:54.992 [main] DEBUG org.hibernate.SQL - insert into springtrans.users (username, password, status) values (?, ?, ?)
    Hibernate: insert into springtrans.users (username, password, status) values (?, ?, ?)
    09:40:55.009 [main] DEBUG o.h.id.IdentifierGeneratorFactory - Natively generated identity: 458
    09:40:55.009 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
    09:40:55.013 [main] DEBUG o.s.orm.hibernate3.HibernateTemplate - Eagerly flushing Hibernate session
    09:40:55.014 [main] DEBUG o.h.e.d.AbstractFlushingEventListener - processing flush-time cascades
    09:40:55.014 [main] DEBUG o.h.e.d.AbstractFlushingEventListener - dirty checking collections
    09:40:55.018 [main] DEBUG org.hibernate.engine.Collections - Collection found: [com.snsystems.data.Users.userSettingses#458], was: [<unreferenced>] (initialized)



    09:40:55.031 [main] DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 13750710550
    09:40:55.032 [main] DEBUG o.h.e.def.AbstractSaveEventListener - executing identity-insert immediately
    09:40:55.032 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
    09:40:55.032 [main] DEBUG org.hibernate.jdbc.ConnectionManager - opening JDBC connection
    09:40:55.032 [main] DEBUG o.s.j.d.DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/test]
    09:40:55.047 [main] DEBUG org.hibernate.SQL - insert into springtrans.user_settings (user_id, last_login_ip, failed_logins) values (?, ?, ?)
    Hibernate: insert into springtrans.user_settings (user_id, last_login_ip, failed_logins) values (?, ?, ?)
    09:40:55.055 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
    09:40:55.061 [main] DEBUG o.h.util.JDBCExceptionReporter - could not insert: [com.snsystems.data.UserSettings] [insert into springtrans.user_settings (user_id, last_login_ip, failed_logins) values (?, ?, ?)]
    com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'last_login_ip' cannot be null

}    

applicationContext.xml
{
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location"><value>/jdbc.properties</value></property>
    </bean>

    <!-- Data Source -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
        <property name="url"><value>${jdbc.url}</value></property>
        <property name="username"><value>${jdbc.username}</value></property>
        <property name="password"><value>${jdbc.password}</value></property>
    </bean>


    <!-- Spring hibernate integration -->   
    <!-- Transaction Manager -->
    <bean id="transactionManager" 
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
      <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!-- Transaction Template Bean -->
    <bean id="transactionTemplate" abstract="true"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager">
            <ref local="transactionManager" />
        </property>
        <property name="transactionAttributes">
            <props>
                <prop key="*">PROPAGATION_REQUIRED</prop>
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="view*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="delete*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>

    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
         <property name="sessionFactory" ref="sessionFactory" />
    </bean> 

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />    
        <property name="mappingResources">    
            <list>
                <value>/com/snsystems/data/Users.hbm.xml</value>
                <value>/com/snsystems/data/UserSettings.hbm.xml</value>
            </list>   
        </property>

        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.generate_statistics">true</prop>
            </props>
        </property>   
    </bean>

    <bean id="usersDao" class="com.snsystems.dao.impl.UsersDaoImpl">
        <property name="hibernateTemplate" ref="hibernateTemplate" />
    </bean>

    <bean id="userSettingsDao" class="com.snsystems.dao.impl.UserSettingsDaoImpl">
        <property name="hibernateTemplate" ref="hibernateTemplate" />
    </bean>

    <bean id="userService" class="com.snsystems.service.impl.UsersServiceImpl">
        <property name="usersDao" ref="usersDao" />
        <property name="userSettingsDao" ref="userSettingsDao" />
    </bean>



  <tx:advice id="txAdvice" transaction-manager="transactionManager">
  <tx:attributes>
    <tx:method name="save*" rollback-for="SNTransException"/>
    <tx:method name="get*" read-only="true"/>
    <tx:method name="*"/>
  </tx:attributes>
  </tx:advice>

  <aop:config>
  <aop:pointcut id="userServiceOperation" expression="execution(* com.snsystems.service..Service.*(..))"/>
  <aop:advisor advice-ref="txAdvice" pointcut-ref="userServiceOperation"/>
  </aop:config>

}

UsersDaoImpl


public class UsersDaoImpl implements IUsersDao {

    private HibernateTemplate hibernateTemplate;

    public void saveOrUpdateUsers(Users users) throws PersistenceException {
        try {
            hibernateTemplate.saveOrUpdate(users);
        } catch (Exception e) {
            throw new PersistenceException(e);
        }

    }

    public void deleteUsers(Users users) throws PersistenceException {
        try {
            hibernateTemplate.delete(users);
        } catch (Exception e) {
            throw new PersistenceException(e);
        }
    }

    public HibernateTemplate getHibernateTemplate() {
        return hibernateTemplate;
    }

    public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
        this.hibernateTemplate = hibernateTemplate;
    }

}



UsersServiceImpl 

public class UsersServiceImpl implements IUsersService
{
    private IUsersDao usersDao = null;

    private IUserSettingsDao userSettingsDao = null;

    public void saveOrUpdateUsers(Users users) throws SNTransException {
        try {
            usersDao.saveOrUpdateUsers(users);
        } catch (PersistenceException e) {
            throw new SNTransException(e);
        }
    }

    public void deleteUsers(Users users) throws SNTransException {
        try {
            usersDao.deleteUsers(users);
        } catch (PersistenceException e) {
            throw new SNTransException(e);
        }
    }


    public void saveOrUpdateUserSettings(UserSettings userSettings) throws SNTransException {
        try {
            userSettingsDao.saveOrUpdateUserSettings(userSettings);
        } catch (PersistenceException e) {
            throw new RuntimeException(e);
        }
    }

    public void deleteUserSettings(UserSettings userSettings) throws SNTransException {
        try {
            userSettingsDao.deleteUserSettings(userSettings);
        } catch (PersistenceException e) {
            throw new SNTransException(e);
        }
    }


..  setters and getters for dao's
}



UsersServiceTest
{
public class UsersServiceTest {

    private static ClassPathXmlApplicationContext context = null;
    private static IUsersService usersService = null;
    private static Users users = null;
    private static UserSettings userSettings = null; 

    @Before
    public void setUp() {
        try {

            context = new ClassPathXmlApplicationContext("applicationContextBack.xml");
            usersService = (IUsersService) context.getBean("userService");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @After
    public void tearDown() throws Exception {
        usersService = null;
        context = null;
    }

    @Test
    public void testSaveOrUpdateUserSettings() throws Exception {

        users = new Users();
        users.setUsername("JUnitTest");
        users.setPassword("JUnitTest");
        users.setStatus("inactive");

        usersService.saveOrUpdateUsers(users);
        assertNotNull("User Id is null", users.getId());

        userSettings = new UserSettings();
        userSettings.setUsers(users);

        usersService.saveOrUpdateUserSettings(userSettings);
        assertNotNull("UserSettings Id is null", userSettings.getId());
    }

}


}
4

2 回答 2

0

您应该为您的服务 (impl) 方法添加@Transactional注释。

例子:

@Transactional
public void saveOrUpdateUsers(Users users) {
   ...
}
于 2013-07-29T04:29:40.823 回答
0

所以你想让spring事务管理器在每次测试后回滚事务?那么Spring TestContext 框架可能会有所帮助

向您的测试类添加注释:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("applicationContext.xml")
@Transactional
public class UsersServiceTest {
}

spring 事务管理器会在测试前自动启动一个新事务,并在测试完成时回滚

于 2013-07-30T00:52:50.440 回答