当前位置: 首页 > 知识库问答 >
问题:

事务回滚本地异常客户端的事务在访问@Singleton时中止

唐元凯
2023-03-14

注意:在花了比我想承认的更多的时间来寻找原因之后,用简短的形式加上一个答案。希望我能给别人省去一些痛苦。

将方法调用委托给用 @Singleton 批注的 EJB 时,容器会引发异常,如下所示:

TransactionRolledbackLocalException Client's transaction aborted 

单一bean没有发生数据访问。

服务BeanImpl.java

@Stateless
@Local
public class ServiceBean extends BaseBean{ 
  @EJB private CacheService cacheService;

  public FooObj getFooFromCache(int id) {
    FooObj fooObj = (FooObj) cacheService.get(id);
    if (fooObj == null) {
      fooObj = getEntityById(FooObj.class, id);
      cacheService.put(id, fooObj);  //This throws exception
    }
    return cacheService.get(id);
  }
}

缓存服务Impl.java

@Singleton
@Startup
public class CacheServiceImpl implements CacheService {
    private Cache cache;

    @PostConstruct
    public void init() {
        CacheManager instance = CacheManager.getInstance();
        cache = instance.getCache("cache");
    }

    @PreDestroy
    public void destroy() {
        CacheManager.getInstance().shutdown();
    }

    public Object get(Object id) {
      return cache.get(id);
    }

    public void put(Object id, Object obj) {
      return cache.put(id, obj);
    }
}

问题为什么调用没有数据访问的单例bean会引发事务异常?

共有3个答案

阳兴朝
2023-03-14

类似的问题发生在我身上。但它是由GlassFish/Payara中的bug引起的,在我的应用程序中没有回滚事务。重新启动域修复了它,如下所述:javax.ejb.TransactionRolled back LocalExc的(Glassfes3 JPA Eclipse Link)

督阿苏
2023-03-14

我碰到了类似的问题,并发现了一件有趣的事情:

在@Startup @Singleton中,我有以下调用

@PostConstruct
public void initHardcodedUsers() {
for (User u : getHardcodedUsers()) {
  if (!userRepository.userExists(u.getName())) {
    userRepository.add(u);
  }
 }
}

UserRepository是一个带有EntityManager的@Stateless EJB。在userExists()方法中,我基本上使用getSingleResult()执行“findUserByName”查询。如果没有可用的结果,JPA将抛出NoResultException。我在userExists()中捕捉到一个,并返回false(“用户不存在”)。

由于 NoResultException 是一个运行时异常,正如我刚刚了解到的那样,这里强制回滚!

最简单的方法是避免调用< code > getsingresult()。我使用< code>getResultList()和< code>setMaxResults(1)来代替它。在没有结果的情况下,这将简单地返回一个空列表,因此没有异常,因此没有回滚的tx。

祝你好运:)

克里斯

赵锐
2023-03-14

简短的回答:检查之前执行的代码堆栈(假设 StackTrace 中没有线索)是否存在被捕获且未传播的异常(因此 StackTrace 中没有线索)。

在这个特殊的例子中,有一个try/cat来创建一个命名查询。如果这个命名查询失败,就会在抓块中执行一个辅助查询。这些查询不需要事务,所以回退查询正确执行并返回预期的实体。

然而

这也(我认为)将事务标记为需要回滚。@Singletonbean有点转移注意力。关于将控制权转移到该bean的一些事情使容器检查了Transaction,而此时Transaction又抛出了异常,但该异常是适当的,因为该事务不再有效。

这个故事的寓意:

  • 倒推到最后一次数据库交互,因为这可能是您的问题所在。
  • 仅仅因为上次数据库交互返回了数据并不意味着它没有问题(这对我来说是杀手)。
 类似资料:
  • 我在tomcat服务器中使用具有多个数据源配置的JTA原子事务。有时我会遇到以下异常: JTA事务意外回滚(可能是由于超时);嵌套的异常是javax。交易回滚异常:事务被设置为仅回滚 出现这种异常的原因是什么?

  • 我正在与用propagation.requires_new注释的方法的奇怪行为作斗争。 以下是TransactionManager的日志:

  • 问题内容: 如果在mysql命令列表中发生任何错误,是否可以自动回滚? 例如类似以下内容的东西: 现在,在执行我希望整个交易失败,因此我应该 不 看到值1在myTable的。但是不幸的是,即使事务有错误,该表也仍使用values1进行伪造。 任何想法,我如何使其回滚?(再次出现任何错误)? 编辑-从DDL更改为标准SQL 问题答案: 您可以使用13.6.7.2。DECLARE … HANDLER语

  • 这很好,但并不总是在代码中抛出运行时异常。因此,我挖掘并发现如下所示的rollbackFor; 现在,我必须更改所有代码,以使用RollBackfor更改@Transactional。但是还有其他方法可以将所有@transaction advice属性更改为rollbackFor=exception.class吗?

  • 我正在使用Spring JpaRepository在我的一个应用程序屏幕中实现CRUD。作为其中的一部分,我正在开发一个功能,用户可以保存所有汽车实体或没有(应该回滚)到数据库。我不确定如何使用Spring Boot、Spring Rest和Spring JPA实现此功能。 下面是我的源代码。 除此之外,我还得到了一个类似 请帮帮我。谢谢你。