Java Spring MVC+;Hibernate@Transactional在异常后不回滚
我正在尝试使用Spring创建一个CMT,它可以在每次出现异常时回滚事务。我的问题是,当我从注释为@Transactional的方法对数据库进行多次更改时,即使在某些操作之后强制使用空指针,它也不会回滚操作。我将感谢任何帮助 请遵循以下代码:Java Spring MVC+;Hibernate@Transactional在异常后不回滚,java,spring,hibernate,spring-mvc,transactions,Java,Spring,Hibernate,Spring Mvc,Transactions,我正在尝试使用Spring创建一个CMT,它可以在每次出现异常时回滚事务。我的问题是,当我从注释为@Transactional的方法对数据库进行多次更改时,即使在某些操作之后强制使用空指针,它也不会回滚操作。我将感谢任何帮助 请遵循以下代码: <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xm
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:annotation-config></context:annotation-config>
<context:component-scan base-package="br.com.test" />
<mvc:annotation-driven/>
<tx:annotation-driven transaction-manager="transactionManager" />
<context:property-placeholder location="classpath:config.properties"></context:property-placeholder>
<bean class="org.springframework.context.support.ResourceBundleMessageSource" id="messageSource" p:basename="Messages">
</bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource"
p:driverClassName="${jdbc.driverClassName}"
p:password="${jdbc.password}"
p:url="${jdbc.url}"
p:username="${jdbc.username}">
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
<bean class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
id="sessionFactory">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
<property name="packagesToScan" value="br.com.test"></property>
</bean>
<mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" />
</beans>
我的服务:
@Service("userService")
public class UserServiceImpl implements UserService {
@Resource(name="userDao")
private UserDao userDao;
@Override
@Transactional
public void saveUpdateDeleteTest() throws GenericException {
User user = new User();
user.setFirstName("Rogerio");
user.setLastName("R");
user.setEmail("r@gmail.com");
user.setPassword("123");
try {
this.userDao.save(user);
User u = this.userDao.findById(12l);
u.setFirstName("changed");
this.userDao.save(u);
User u2 = this.userDao.findById(11l);
this.userDao.delete(u2);
u2 = null;
u2.getCreated(); //Forcing a null pointer here
} catch (GenericException ge) {
throw ge;
} catch (Exception e) {
throw new ServiceException("Error at saving user. " + e.getMessage(), e);
}
}
我的刀:
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Autowired
private SessionFactory sessionFactory;
public void save(User user) throws DaoException {
try {
if (user.getId() == null) {
user.setCreated(new Date());
} else {
user.setLastUpdated(new Date());
}
this.sessionFactory.getCurrentSession().saveOrUpdate(user);
} catch (Exception e) {
throw new DaoException("Error at saving user.", e);
}
}
public void delete(User user) throws DaoException {
try {
this.sessionFactory.getCurrentSession().delete(user);
} catch (Exception e) {
throw new DaoException("Data access error. " + e.getMessage(), e);
}
}
public User findById(Long id) throws DaoException {
try {
Query query = this.sessionFactory.getCurrentSession().createQuery(
"from User u where u.id = :id");
query.setLong("id", id);
List<User> list = query.list();
User returnedObject = null;
if (list != null && list.size() > 0) {
returnedObject = list.iterator().next();
}
return returnedObject;
} catch (Exception e) {
throw new DaoException("Data access error. " + e.getMessage(), e);
}
}
}
@Repository(“userDao”)
公共类UserDaoImpl实现UserDao{
@自动连线
私人会话工厂会话工厂;
public void save(用户)引发异常{
试一试{
if(user.getId()==null){
user.setCreated(新日期());
}否则{
user.setLastUpdated(新日期());
}
this.sessionFactory.getCurrentSession().saveOrUpdate(用户);
}捕获(例外e){
抛出新的异常(“保存用户时出错。”,e);
}
}
公共void delete(用户)引发异常{
试一试{
this.sessionFactory.getCurrentSession().delete(用户);
}捕获(例外e){
抛出新的DaoException(“数据访问错误”。+e.getMessage(),e);
}
}
公共用户findById(长id)引发异常{
试一试{
Query Query=this.sessionFactory.getCurrentSession().createQuery(
“来自用户u,其中u.id=:id”);
query.setLong(“id”,id);
List=query.List();
用户returnedObject=null;
if(list!=null&&list.size()>0){
returnedObject=list.iterator().next();
}
返回返回对象;
}捕获(例外e){
抛出新的DaoException(“数据访问错误”。+e.getMessage(),e);
}
}
}
您的事务没有回滚,因为没有引发异常,换句话说,saveUpdateDeleteTest
正在捕获异常,这就是为什么spring事务代理无法检测到任何异常,因此没有回滚。移除catch块,您将看到事务将回滚。请注意,回滚遵循EJB约定,即
而EJB的默认行为是让EJB容器
在系统异常时自动回滚事务(通常为
运行时异常),EJBCMT不会回滚事务
在应用程序异常(即,选中
除java.rmi.RemoteException之外的异常)。而春天
声明性事务管理的默认行为遵循EJB
约定(仅在未检查的异常情况下自动回滚),它
用于自定义此项
因此,在您的情况下,如果希望在任何异常情况下回滚事务,则需要进行自定义,如下所示:
@Transactional(rollbackFor = Exception.class)
您的回答是对的,但为什么spring在接收到NullPointerException时回滚事务,而在接收到ServiceException时却没有回滚,因为ServiceException是扩展exception类的异常?是否有一些特定类型的os ExceptionOS必须抛出才能进行Spring回滚事务?找到了解决方案的最后一部分,我需要使用@Transactional(rollboor=genericeException.class)来指定我自己的异常,这些异常应该导致Spring上的回滚。谢谢=)
@Transactional(rollbackFor = Exception.class)