如何在 entitymanager createNativeMethod 中回滚

how to rollback in entitymanager createNativeMethod

我正在使用实体管理器的本机方法,当出现某些错误时我想回滚 occurs.For 我尝试了 @Transactional 注释,但这没有 rollback.Below 是我的示例代码

控制器

@Autowired
ServiceImpl ServiceImpl;

@RequestMapping("/saveinfo")
@ResponseBody
@Transactional
public String saveinfo(Long id)
{
   ServiceImpl.saveInfo(id);
}

服务class

@Autowired
DAOImpl daoImpl;

@Transactional
public String saveinfo(Long id)
{
    daoImpl.saveInfo1(id);
    daoImpl.saveInfo12(id);
    daoImpl.saveInfo12(id);

}

DAO class

@Override
public BigInteger saveInfo11() {

   Query query =  entityManagerUtil.entityManager().createNativeQuery("insert query");
   return (BigInteger)query.getSingleResult();
}

@Override
public BigInteger saveInfo12() {

   Query query =    entityManagerUtil.entityManager().createNativeQuery("insert query");
   return (BigInteger)query.getSingleResult();
}

@Override
public BigInteger saveInfo13() {

   Query query =    entityManagerUtil.entityManager().createNativeQuery("insert query");
   return (BigInteger)query.getSingleResult();
}

现在在上面的代码中,

如果我在 saveInfo3() 中有一些运行时错误,那么我想回滚方法 saveInfo1()saveInfo2()

我是这样做的,但是没有回滚,所以请告诉我怎么做

编辑

我尝试使用

@Transactional(rollbackFor=MyException.class,propagation = Propagation.REQUIRED) and  @Transactional(propagation = Propagation.REQUIRED) and

@Transactional(rollbackFor=MyException.class))

3种情况都没有回滚

更新

applicationcontext.xml



<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
       xmlns:aop="http://www.springframework.org/schema/aop" 
       xmlns:context="http://www.springframework.org/schema/context" 
       xmlns:jee="http://www.springframework.org/schema/jee" 
       xmlns:tx="http://www.springframework.org/schema/tx" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:security="http://www.springframework.org/schema/security" 
       xmlns:mongo="http://www.springframework.org/schema/data/mongo"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/aop 
                          http://www.springframework.org/schema/aop/spring-aop-3.0.xsd        
                          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/data/mongo
                          http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd         
                          http://www.springframework.org/schema/jee 
                          http://www.springframework.org/schema/jee/spring-jee-3.0.xsd         
                          http://www.springframework.org/schema/tx  
                          http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
                          http://www.springframework.org/schema/security 
                          http://www.springframework.org/schema/security/spring-security-3.0.xsd
                          http://www.springframework.org/schema/task  
http://www.springframework.org/schema/task/spring-task-3.0.xsd">



     <!--<context:annotation-config />-->
     <context:spring-configured/>

       <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
        <property name="dataSource" ref="dataSource"/>
        <property name="persistenceUnitName" value="persistenceUnit"/>
       </bean>
       <bean id="messageDigestPasswordEncoder" class="org.springframework.security.authentication.encoding.MessageDigestPasswordEncoder">
         <constructor-arg value="SHA-256" />
        </bean>

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


    </bean>










     <tx:annotation-driven  mode="aspectj" transaction-manager="transactionManager"/>
       <context:property-placeholder location="classpath*:META-INF/database.properties"/>
       <context:property-placeholder location="classpath*:META-INF/project.properties"/>

      <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
     </bean>

    <bean id="propertiesUtil" class="com.work.project.utils.PropertiesUtil">

    <property name="locations" >
   <list>
                <value>classpath*:META-INF/*.properties</value>

            </list>
    </property>

</bean>

    <context:component-scan base-package="com.work.project">
        <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>



     <task:executor id="myexecutor" pool-size="5"  />
<task:annotation-driven executor="myexecutor"/>








</beans>

修改控制器方法

@Autowired
ServiceImpl ServiceImpl;

@RequestMapping("/saveinfo")
@ResponseBody
//Now I dont use transactional annotation in controller class
public String saveinfo(Long id)
{
   ServiceImpl.saveInfo(id);
}

如果需要更多信息,请询问

您需要更改您的方法,为您的 @Transactional 注释添加 rollbackFor 属性,这样

@Transactional(rollbackFor=MyException.class)
public String saveinfo(Long id)

请记住,MyException 应该是未检查异常,因为从 @Transactional 方法抛出的已检查异常不会导致事务回滚。

更新:

确保一切正确

  1. 检查 Spring 确实创建了代理并且您的方法正在事务中执行(例如使用 TransactionSynchronizationManager.isActualTransactionActive()

  2. 检查MyException.class确实是未经检查的异常(java.lang.RuntimeExceptionjava.lang.Error的子类)

  3. 检查你的异常是否确实被抛出(例如没有被捕获)

为什么您的控制器 saveInfo() 被标记为事务性的?不推荐这样做,只有服务层应该被标记为事务性的。例如参见 [​​=20=] post。

问题似乎是 EntityManager 没有被 Spring 注入。 EntityManager 实例由您的实用程序 class entityManagerUtil.entityManager() 创建。这意味着,每次当您使用新的 EntityManager 时,它们都不是您方法事务的一部分。

为了解决这个问题:让 Spring 正确注入 EntityManager(例如,尝试使用 @PersistenceContext 将其直接注入到您的原始 bean 中,然后直接在同样的单一方法)。


更新: 问题是抛出异常的代码在 try/catch 块中,这样,事务就不会被 Spring 回滚。仅当事务方法以 RuntimeException(默认情况下)退出时,事务才会回滚。

也许 entityManagerUtil(您在 DAO 实现中使用)使用或创建了一个实体管理器,它在周围的事务上下文中不是 运行。请看下面的 tutorial:这里 JPA EntityManager 注入了 @PersistenceContext

你能确定你的 persistenceUnit 已经配置了以下 transaction type(可选)和 hibernate.connection.autocommitfalse,如果没有,请这样做。

<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
        <properties>
            <property name="hibernate.connection.autocommit" value="false" />
        </properties>
    </persistence-unit>

为简洁起见,我排除了其他属性