EDIT: Thanks everybody for your answers, but the problem was with my data source configuration, which was actually in auto-commit mode. See my answer below for details.
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:
This is the table creation script:
CREATE TABLE test(
id INTEGER NOT NULL,
name VARCHAR2(20),
CONSTRAINT test_pk PRIMARY KEY ("ID")
);
CREATE SEQUENCE test_seq;
This is the corresponding entity:
@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...
}
And the test web service:
@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();
}
}
My understanding is that:
- 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.
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?
EJBContext
to my bean and callcontext.setRollbackOnly();
I still get the row in the table. – Gannon