Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/370.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring MVC+;Hibernate@Transactional在异常后不回滚_Java_Spring_Hibernate_Spring Mvc_Transactions - Fatal编程技术网

Java Spring MVC+;Hibernate@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

我正在尝试使用Spring创建一个CMT,它可以在每次出现异常时回滚事务。我的问题是,当我从注释为@Transactional的方法对数据库进行多次更改时,即使在某些操作之后强制使用空指针,它也不会回滚操作。我将感谢任何帮助

请遵循以下代码:

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