4

我有一个基于 Maven 的 Java EE 项目,应该在 GlassFish v3 上运行。有一个注入 EJB 服务的 JSF ManagedBean。ManagedBean 在发生一些 JPA 操作(创建新实体对象、持久化、刷新)的按钮单击时调用注入的 EJB 方法之一。当被EntityManager.flush()调用时,它会引发异常:

Caused by: javax.persistence.TransactionRequiredException:  Exception
Description: No transaction is currently active

数据源是具有 JTA 事务类型的 jta 数据源(在 persistence.xml 中定义)。

我已经找到了解决方案,但由于部署问题,它并不令人满意。如果我将下一行代码放入persistence.xml,那么它可以毫无问题地运行:

<property name="eclipselink.target-server" value="SunAS9"/>

由于这个原因,我假设这是一个部署问题,当 eclipselink 无法识别 JTA 管理器时。

任何建议将不胜感激,谢谢!

更新:

@MRalwasser:这是完整的堆栈跟踪。(对不起,我不得不删除真正的包名,它现在是 masked.package.name)pastebin 上的堆栈跟踪

@Chris:对不起,我忘了提,GeneriDao 类通过工厂方法创建实体管理器,而不是通过依赖注入。

4

2 回答 2

0

默认情况下,只有 EJB 可以在 CMT 中工作。在托管 bean 或 CDI bean 中,您必须实现自己的机制来处理事务并在其中运行您的服务。

public class ManagedBean {        

    @Inject
    yourEjbService service;

    @Resource
    UserTransaction utx;

    public void save(){
        try{
            utx.begin();
            service.doAction();
            utx.commit();
        } catch (Exception e) {
            try {
                utx.rollback();
            } catch (Exception ex) {
                ...
            } 
        }
    }
    ...
 }

如果您EntityManager.flush()使用@PersistenceContext. 它会在 EJB 中的每个方法结束后自动分离实体。

于 2013-07-25T11:40:22.460 回答
0

Java Enterprise 的持久性控制机制有几个选项和特定的设计选择。在我使用的几乎所有 Java EE 实现中,都使用了容器管理事务 (CMT)。在偶尔的情况下,可以选择 bean 管理事务 (BMT)。

当您需要确定“提交”(或“回滚”)在程序执行期间发生的确切时间时,可以首选Bean 管理的事务。这在高性能的时间关键型应用领域可能是必需的。有关 BMT 的示例,请参见示例中的“Bean Managed Transactions”部分,Bean Managed Transactions

容器管理事务意味着应用服务器(“容器”)中的软件在使用持久性上下文的 Java 代码执行之前调用“开始”事务。当代码执行完成时(当调用树返回时,例如作为网络请求的结果),应用服务器调用'commit'。因此,修改后的实体实际上在应用程序数据库中更新。

在 Java EE 中,语句:@TransactionManagement(TransactionManagementType.CONTAINER)@TransactionManagement(TransactionManagementType.BEAN)分别表示容器管理事务或 bean 管理事务。Java EE 定义了几种类型的 bean:会话驱动 bean、消息驱动 bean、本地 bean。这些 bean 通常是@Stateless,并且都可以与容器管理的事务一起使用。

在 EE 中可以通过添加注释来指定容器管理事务处理的详细控制:

@TransactionAttribute(REQUIRES_NEW) 
public void myTopLevelMethodWhichStartsNewInnerTransaction()
....
@TransactionAttribute(REQUIRED)
public void myTopLevelMethodContinueExistingTransactionIfAny()
....
@TransactionAttribute(NEVER)
public void myNoCurrentTransactionAllowedWhenMethodCalled()
....

冲洗

调用“flush”以确保数据库缓存写入磁盘的必要性取决于所使用的数据库类型。例如,对于 Postgress 调用flush会有所不同,而对于内存数据库 'derby',flush 没有效果,并且在后一种情况下可能会导致类似于此问题中报告的错误。因此,效果flush取决于数据库。

于 2017-05-10T22:12:53.003 回答