EntityManager.flush()在Java Web服务中提交事务 [英] EntityManager.flush() commits the transaction in a Java web service

查看:929
本文介绍了EntityManager.flush()在Java Web服务中提交事务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑:感谢大家的回答,但问题出在我的数据源配置上,该配置实际上处于自动提交模式.有关详细信息,请参见我在下面的答案.

两个 EntityManager.flush()方法并在Google中进行搜索似乎表明flush方法仅将待处理语句发送到数据库,而不提交事务.但是我创建的一个简单的测试Web服务(在Java 7,Oracle 11gR2,JBoss 7.1中,并且该Web服务打包为jar文件)似乎表明并非如此:

Both the Javadoc of the EntityManager.flush() method and searching for it in Google seem to suggest that the flush method only sends the pending statements to the database and does not commit the transaction. But a simple test web service I created (in Java 7, Oracle 11gR2, JBoss 7.1 and the Web service is packaged as a jar file) seem to indicate otherwise:

这是表创建脚本:

CREATE TABLE test(
    id INTEGER NOT NULL,
    name VARCHAR2(20), 
    CONSTRAINT test_pk PRIMARY KEY ("ID")
);
CREATE SEQUENCE test_seq;

这是对应的实体:

@Entity @Table(name = "TEST")
public class Test implements Serializable {

    private static final long serialVersionUID = 9192814682033048425L;

    @Id @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TEST_SEQ")
    @SequenceGenerator(name="TEST_SEQ",sequenceName="TEST_SEQ", allocationSize = 1)
    private Integer id;

    @Column(name = "NAME")
    private String name;

    // Getters and setters...
}

测试Web服务:

@Stateless @WebService(serviceName = "TestService")
@TransactionManagement(TransactionManagementType.CONTAINER)
public class TestServiceBean implements TestService {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public void createTest(String name) {
        Test test = new Test();
        test.setName(name);
        entityManager.persist(test);
        entityManager.flush();

        throw new RuntimeException();
    }
}

我的理解是:

  • 调用createTest方法时,应用程序开始新的事务
  • persist()方法生成一个INSERT语句,将其发送到数据库
  • flush()方法将INSERT语句发送到数据库,但不提交事务!
  • RuntimeException导致事务回滚.
  • When the createTest method is called, the application starts a new transaction
  • The persist() method generates an INSERT statement to be sent to the database
  • The flush() method sends the INSERT statement to the database but does not commit the transaction!
  • The RuntimeException causes the transaction to rollback.

但是显然我的理解是错误的:每次我运行Web服务方法时,表中都会出现一个新行.此外,使用调试器进入此方法揭示了在调用flush()方法时插入了该行(我可以使用SQL Developer从另一个数据库会话中查看"该行).

But obviously my understanding is wrong: every time I run the web service method I get one new row in the table. Moreover, stepping into this method with a debugger reveals that the row is inserted when the flush() method is called (I can "see" the row from another db session using SQL Developer).

有人可以解释这种行为吗?

Can someone please explain this behavior?

推荐答案

flush()似乎没有什么问题.问题是我没有在JBoss中正确设置数据源.这里的教训是,如果您想在EBJ中使用容器管理的事务,则需要:

It seems that there is nothing wrong with flush() after all. The problem was that I didn't set up the data source correctly in JBoss. The lesson here is that if you want to use container managed transactions in EBJs then you need to:

  • 在JBoss中,选中数据源配置中的使用JTA?复选框.
  • 在Weblogic中,选中数据源配置的交易"标签中的"<支持全球交易"复选框.
  • In JBoss, check the Use JTA? check box in the data source configuration.
  • In Weblogic, check the Supports Global Transactions check box in the Transactions tab of the data source configuration.

此外,为了消除任何混乱,我代码中的事务管理是正确的.抛出RuntimeException 回滚异常.这是为什么?好吧,来自Java EE 6教程,我们有:

Additionally, and in order to clear any confusion, the transaction management in my code is correct. Throwing a RuntimeException does rollback the Exception. Why is that? Well, from the Java EE 6 tutorial we have:

如果引发系统异常,则容器将自动回滚事务.

if a system exception is thrown, the container will automatically roll back the transaction.

但是什么是系统异常?该教程似乎没有进一步涉及该主题,因此让我们搜索 EJB规范.在第382页中,我们有:

But what is a system exception? The tutorial does not seem to touch upon the subject any further, so lets search the EJB spec. In page 382 we have:

系统异常是一个异常,它是java.rmi.RemoteException(或其子项之一, 类)或不是应用程序异常的RuntimeException.

A system exception is an exception that is a java.rmi.RemoteException (or one of its sub- classes) or a RuntimeException that is not an application exception.

好,那么也许RuntimeException是一个应用程序异常吗?不,不是,因为在第380页中我们有以下内容:

OK, so maybe the RuntimeException is an application exception then? No it is not, because in page 380 we have this:

作为检查异常的应用程序异常可以通过在bean的业务接口,无接口视图,主接口,组件接口和Web服务端点的方法的throws子句中列出来进行定义.通过使用ApplicationException元数据批注对其进行注释,或通过使用application-exception元素在部署描述符中对其进行注释,可以将作为未经检查的异常的应用程序异常定义为应用程序异常.

Application exceptions that are checked exceptions may be defined as such by being listed in the throws clauses of the methods of the bean’s business interface, no-interface view, home interface, component interface, and web service endpoint. An application exception that is an unchecked exception is defined as an application exception by annotating it with the ApplicationException metadata annotation, or denoting it in the deployment descriptor with the application-exception element.

因此,因为我没有做任何上面列出的事情,所以我在代码中引发的异常确实是系统异常,并且如果您已设置数据源以使用JTA,则确实回滚了事务 .

So, because I didn't do any of the things listed above, the exception I throw in my code is indeed a system exception and indeed rolls back the transaction if you have set up your data source to use JTA.

这篇关于EntityManager.flush()在Java Web服务中提交事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆