编辑:感谢大家的回答,但问题出在我的数据源配置上,它实际上处于自动提交模式。有关详细信息,请参阅下面的答案。
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...
}
和测试网络服务:
@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 服务方法时,我都会在表中得到一个新行。此外,使用调试器单步执行此方法会显示在调用该方法时插入了该行flush()
(我可以使用 SQL Developer 从另一个数据库会话“看到”该行)。
有人可以解释这种行为吗?