如何在EntityManager中使用createNativeMethod进行回滚操作

7 浏览
0 Comments

如何在EntityManager中使用createNativeMethod进行回滚操作

我正在使用实体管理器的本地方法,当发生错误时,我想回滚。为此,我尝试了@Transactional注解,但是它没有回滚。以下是我的示例代码:

控制器

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

服务类

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

DAO类

@Override
public BigInteger saveInfo11() {
   Query query =  entityManagerUtil.entityManager().createNativeQuery("插入查询");
   return (BigInteger)query.getSingleResult();
}
@Override
public BigInteger saveInfo12() {
   Query query =    entityManagerUtil.entityManager().createNativeQuery("插入查询");
   return (BigInteger)query.getSingleResult();
}
@Override
public BigInteger saveInfo13() {
   Query query =    entityManagerUtil.entityManager().createNativeQuery("插入查询");
   return (BigInteger)query.getSingleResult();
}

现在在上述代码中,

如果saveInfo3()中发生运行时错误,我希望回滚saveInfo1()saveInfo2()方法。

这是我做的方式,但是它没有回滚,所以请告诉我应该怎么做。

编辑

我尝试使用@Transactional(rollbackFor=MyException.class,propagation = Propagation.REQUIRED)@Transactional(propagation = Propagation.REQUIRED)@Transactional(rollbackFor=MyException.class)

在这3种情况下,它都没有回滚。

更新

applicationcontext.xml


     
     
       
        
        
       
       
         
        
       
         
        
        
        
    
     
       
       
      
        
     
    
    
   
                classpath*:META-INF/*.properties
            
    

    
        
    
     


修改后的控制器方法

@Autowired
ServiceImpl ServiceImpl;
@RequestMapping("/saveinfo")
@ResponseBody
//现在我不在控制器类中使用事务注解
public String saveinfo(Long id)
{
   ServiceImpl.saveInfo(id);
}

如果需要更多信息,请告诉我。

0
0 Comments

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

为了解决这个问题:让Spring正确地注入EntityManager(例如,尝试直接在原始bean中注入它,使用@Autowired注解),并将这三个方法直接放在同一个方法中。

更新:

问题是因为抛出异常的代码在try/catch块中,这样,Spring不会回滚事务。事务只在事务性方法以RuntimeException退出时回滚(默认情况下)。

0
0 Comments

出现原因:entityManagerUtil可能使用或创建了一个不在周围事务上下文中运行的实体管理器。

解决方法:请参考以下教程:在这里,JPA EntityManager使用javax.persistence.PersistenceContext注解进行注入。

@PersistenceContext
private EntityManager entityManager;

这样可以确保EntityManager在正确的事务上下文中运行。

0
0 Comments

问题的原因是在使用EntityManager的createNativeQuery方法执行本地查询时,事务没有回滚。解决方法是在saveinfo方法上使用rollbackFor属性来设置回滚的异常类型。

具体解决方法如下:

1. 修改saveinfo方法,添加rollbackFor属性来设置回滚的异常类型:

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

2. 确认MyException是一个unchecked异常,即它是RuntimeException或Error的子类。

3. 确认异常确实被抛出,没有被捕获。

另外,需要注意的是,saveInfo方法作为控制器方法,标记为事务的操作是不推荐的,只有服务层应该标记为事务。详情请参考链接:https://stackoverflow.com/questions/23118789

感谢回答,我之前尝试过这种方法,但是没有回滚。这个回滚只在HQL中起作用,而在本地查询中却没有。

请您更新一下您尝试的代码。(我在我的回答中添加了一些信息)

我已经修改了问题。

看起来一切都是正确的。所以回滚应该起作用。再次确保以下几点:1. Spring确实创建了事务(使用TransactionSynchronizationManager.isActualTransactionActive()方法);2. MyException是一个unchecked异常;3. 确认MyException确实被抛出。

请参考这个链接中的代码:http://pastie.org/9974005。在运行saveinfo1和saveinfo2之后,它将在第8行抛出NullPointerException异常。所以我在saveinfo1和saveinfo2中插入的内容应该被回滚,但实际上没有发生。我在数据库中检查,发现所有的内容都还存在。

0