編集:皆さんの回答に感謝しますが、問題は私のデータソース構成にあり、実際には自動コミットモードでした。詳細については、以下の私の回答を参照してください。
EntityManager.flush()メソッドのJavadocとGoogleでの検索はどちらも、flush
メソッドが保留中のステートメントのみをデータベースに送信し、トランザクションをコミットしないことを示唆しているようです。しかし、私が作成した単純なテストWebサービス(Java 7、Oracle 11gR2、JBoss 7.1、およびWebサービスはjarファイルとしてパッケージ化されています)は、そうでないことを示しているようです。
これはテーブル作成スクリプトです。
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により、トランザクションがロールバックされます。
しかし、明らかに私の理解は間違っています。Webサービスメソッドを実行するたびに、テーブルに1つの新しい行が表示されます。さらに、デバッガーを使用してこのメソッドにステップインすると、flush()
メソッドが呼び出されたときに行が挿入されていることがわかります(SQL Developerを使用して別のデータベースセッションから行を「見る」ことができます)。
誰かがこの振る舞いを説明できますか?