我正在使用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());
}
}
}
答案 0 :(得分:0)
您应该为服务(impl)方法添加@Transactional
注释。
示例:
@Transactional
public void saveOrUpdateUsers(Users users) {
...
}
答案 1 :(得分:0)
所以你希望spring transaction Manager在每次测试后回滚事务吗?那么Spring TestContext Framework可能有帮助
为测试类添加注释:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("applicationContext.xml")
@Transactional
public class UsersServiceTest {
}
spring transaction manager将在测试之前自动启动一个新事务,并在测试结束时将其回滚