TransactionRolledbackLocalException访问@Singleton时客户端的事务中止

时间:2012-10-18 06:06:31

标签: java jpa transactions ejb-3.1

注意:在花费的时间远远超过我想要找到原因的时候,用简短的形式添加这个问题。希望我能为别人带来一些痛苦。

将方法调用委托给注释为EJB的{​​{1}}时,容器会抛出以下行的异常:

@Singleton

Singleton bean无法访问数据。

ServiceBeanImpl.java

TransactionRolledbackLocalException Client's transaction aborted 

CacheServiceImpl.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);
  }
}

问题 为什么调用不进行数据访问的Singleton bean会引发Transaction异常?

3 个答案:

答案 0 :(得分:6)

简答: 检查先前执行的代码堆栈(假设StackTrace中没有线索),以获取被捕获但未传播的异常(因此StackTrace中没有线索)。

在这种特殊情况下,创建命名查询时出现try/catch。如果该命名查询失败,则在catch块中执行辅助查询。查询不需要事务,因此回退查询正确执行并返回预期的实体。

...然而

那也(我认为)标志着交易需要回滚。 @Singleton豆有点像红鲱鱼。关于将控制转移到该bean的事情使得容器检查了Transaction,而Transaction又在那时抛出了异常,但是由于事务不再有效,异常​​是合适的。

故事的道德:

  • 向后工作到最后一次数据库交互,因为这可能是你的问题所在。
  • 仅仅因为最后一次数据库交互返回数据并不意味着它没有问题(这对我来说是杀手)。

答案 1 :(得分:2)

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

在@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是一个RuntimeException,所以我在这里强制回滚,就像我刚刚学到的那样!

最简单的方法是避免调用getSingleResult()。而不是我使用getResultList()setMaxResults(1)。如果没有结果,那将只返回一个空List,因此没有异常,因此没有回滚tx。

祝你好运:)

克里斯

答案 2 :(得分:0)

我在GlassFish / Payara Server中遇到TransactionRolledbackLocalException的类似问题。但这是由GlassFish / Payara中的错误引起的,没有任何内容回滚到我的应用程序中。重新启动域以对其进行修复,如下所述:javax.ejb.TransactionRolledbackLocalException (Glassfish 3 + JPA + EclipseLink)