【问题标题】:EJB transaction managementEJB 事务管理
【发布时间】:2017-03-29 07:33:17
【问题描述】:

我正在尝试了解 EJB 事务管理。我编写了以下代码并部署在 websphere liberty 中

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class BookRepositoryBean {

  @Resource(lookup = "jdbc/mydb")
  private DataSource dataSource;

  public void create(List<Book> books) {

  try {
    for(Book book: books) {
      Connection con = dataSource.getConnection();
      PreparedStatement stmt = con.preparedStatement("insert into ....");
      stmt.setString(1, ...);
      stmt.executeUpdate();
    }
  } catch(SQLException e) {
    throw new RuntimeException(e.getMessage());
  }
}

我的 server.xml 如下所示

<dataSource jndiName="jdbc/mydb" transactional="false">
....
</dataSource>

我在具有主键约束的表中手动插入了一条记录,然后尝试运行我的代码来保留两条记录,其中一条是重复记录,另一条是新记录。

我尝试了不同的选项并观察到以下情况

  1. 服务器 XML 数据源:transactional=false
    TransactionManagementType=BEAN
    结果:1/2 记录被保留。由于没有交易 编写管理代码,这是意料之中的。

  2. 服务器 XML 数据源:transactional=true
    TransactionManagementType=CONTAINER
    结果:0/2 条记录保持不变。由于启用了事务管理 已插入 0 条记录。

  3. 服务器 XML 数据源:transactional=false
    TransactionManagementType=CONTAINER
    结果:保留 1/2 条记录

  4. 服务器 XML 数据源:transactional=true
    TransactionManagementType=BEAN
    结果:1/2 记录被保留。我明白了,因为我关闭了 代码级别的事务管理,已保存 1 条记录。

  5. 服务器 XML 数据源:transactional=true
    删除了 @Stateless 和 @TransactionManagement 注释
    结果:0/2 条记录被保留。

在案例 3 中,我不明白为什么要插入 1 条记录。我假设容器级别的事务管理只有在代码中启用并且在容器级别启用时才会起作用。我说的对吗?

在案例 5 中,我不明白为什么当类不是 EJB 时会保留 0 条记录。我一直认为事务管理仅适用于 EJB。这个测试证明我错了。现在我不明白为什么要选择 EJB 而不是常规的 java 类。

谁能解释一下?

【问题讨论】:

    标签: jakarta-ee ejb ejb-3.0 websphere-liberty transactional


    【解决方案1】:
    1. 服务器 XML 数据源:transactional=false
      TransactionManagementType=CONTAINER
      结果:保留 1/2 条记录

      在案例 3 中,我不明白为什么要插入 1 条记录。我假设容器级别的事务管理只有在代码中启用并且在容器级别启用时才会起作用。我说的对吗?

    即使容器在此 EJB 中管理事务,如果资源无法参与事务(即 transactional=false),则每个操作都会单独执行。插入重复键失败,插入另一个键成功。

    【讨论】:

    • 那么,在第 5 种情况下,如果我在 jboss 或任何其他没有 LTE 的应用程序服务器中运行相同的代码,是否会保留记录?
    • 原来我的案例 #5 不正确。这不是 LTC 的工作方式,所以我已经删除了我的答案的那部分。
    【解决方案2】:

    关于#5,通过删除注释并让它成为一个普通的java类,它在调用者的事务和上下文下运行。调用者是另一个具有容器管理事务的 EJB 吗?

    【讨论】:

    • 是的,调用者是一个 EJB。谢谢指点。我将尝试通过删除调用者上的无状态注释来再次测试它。
    • 我删除了调用者的无状态注释并进行了测试。 1/2 记录被持久化。感谢您指出问题。
    猜你喜欢
    • 2012-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多