使用普通 JDBC 在 DAO 或服务层中处理事务

Transaction handling in DAO or Service layer using plain JDBC

假设我有 classes AccountPayment.

Class 帐号

public class Account {
    private Integer id;
    private Integer accountHolderId;
    private BigDecimal balance;
    private Byte status;  // 0: account is fine, 1: locked, can't make payments.

    // Getters and Setters
}

Class 付款

public class Payment {
    private Integer id;
    private BigDecimal amount;
    private Integer senderId;
    private Integer receiver;
    private Integer paymentStatusId;

    // Getters and Setters
}


DAO 层AccountDaoPaymentDao class 实现 CRUD 方法。下一个是 服务层,它有 AccountServicePaymentService classes,在 DAO class 之上进行额外的操作es。

由于我使用的是 currency/money,所以我使用的是 transactions。我在我的 DAO classes 中使用它们。

我的 DaoFactory class 有一个方法 createConnection() returns 每个特定 DaoFactory(例如 MySqlDaoFactory)的连接对象,它已启用事务使用 connection.setAutoCommit(false); 的功能。所以每次我连接到数据库时,我手动使用 commit()rollback() 方法。


问题

假设我想从一个帐户(发送方)向另一个帐户(接收方)付款。场景如下所示:

  1. 检查是否 sender.status == 0,这意味着它已解锁并可以发送付款。
  2. 查看他的余额中是否he has more or equals amount of money他想发送。
  3. 从他的账户中提取这笔钱。
  4. 检查是否receiver.status == 0,表示已解锁,可以收钱
  5. 在收款人账户上存入金额。
  6. 将付款状态更改为1,即成功。

这个场景告诉我们使用两个 DAO 实例:AccountDaoPaymentDao 并从这些实例调用方法。当我在 PaymentService 中实现这个场景时,它是实现事务的正确方法吗?

由于您没有使用某些框架,例如 Spring Transaction(我强烈建议您使用),我建议您执行以下操作:

  1. 只使用一个 DAO class 来创建您需要的所有业务流程并在那里使用交易。
  2. 在服务层创建连接,并将其作为参数传递给您在业务流程中需要的所有 DAO。我不喜欢这种方式,因为您会将连接控制委托给服务层,而不是数据访问层。
  3. 将 JDBC 更改为使用 Spring Transaction,这将允许您注释将在服务层中的同一事务中的方法,尽管它们位于不同的 DAO 中。这是可行的,因为 Spring 将控制连接,因此它将通过 DAO 注入相同的连接。看看这个 例子

更多的是设计偏好问题,然后才是正确的