使用普通 JDBC 在 DAO 或服务层中处理事务
Transaction handling in DAO or Service layer using plain JDBC
假设我有 classes Account
和 Payment
.
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 层 有 AccountDao
和 PaymentDao
class 实现 CRUD 方法。下一个是 服务层,它有 AccountService
和 PaymentService
classes,在 DAO class 之上进行额外的操作es。
由于我使用的是 currency/money,所以我使用的是 transactions。我在我的 DAO classes 中使用它们。
我的 DaoFactory
class 有一个方法 createConnection()
returns 每个特定 DaoFactory(例如 MySqlDaoFactory
)的连接对象,它已启用事务使用 connection.setAutoCommit(false);
的功能。所以每次我连接到数据库时,我手动使用 commit()
和 rollback()
方法。
问题
假设我想从一个帐户(发送方)向另一个帐户(接收方)付款。场景如下所示:
- 检查是否
sender.status == 0
,这意味着它已解锁并可以发送付款。
- 查看他的余额中是否
he has more or equals amount of money
他想发送。
- 从他的账户中提取这笔钱。
- 检查是否
receiver.status == 0
,表示已解锁,可以收钱
- 在收款人账户上存入金额。
- 将付款状态更改为1,即成功。
这个场景告诉我们使用两个 DAO 实例:AccountDao
和 PaymentDao
并从这些实例调用方法。当我在 PaymentService
中实现这个场景时,它是实现事务的正确方法吗?
由于您没有使用某些框架,例如 Spring Transaction(我强烈建议您使用),我建议您执行以下操作:
- 只使用一个 DAO class 来创建您需要的所有业务流程并在那里使用交易。
- 在服务层创建连接,并将其作为参数传递给您在业务流程中需要的所有 DAO。我不喜欢这种方式,因为您会将连接控制委托给服务层,而不是数据访问层。
- 将 JDBC 更改为使用 Spring Transaction,这将允许您注释将在服务层中的同一事务中的方法,尽管它们位于不同的 DAO 中。这是可行的,因为 Spring 将控制连接,因此它将通过 DAO 注入相同的连接。看看这个 例子
更多的是设计偏好问题,然后才是正确的
假设我有 classes Account
和 Payment
.
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 层 有 AccountDao
和 PaymentDao
class 实现 CRUD 方法。下一个是 服务层,它有 AccountService
和 PaymentService
classes,在 DAO class 之上进行额外的操作es。
由于我使用的是 currency/money,所以我使用的是 transactions。我在我的 DAO classes 中使用它们。
我的 DaoFactory
class 有一个方法 createConnection()
returns 每个特定 DaoFactory(例如 MySqlDaoFactory
)的连接对象,它已启用事务使用 connection.setAutoCommit(false);
的功能。所以每次我连接到数据库时,我手动使用 commit()
和 rollback()
方法。
问题
假设我想从一个帐户(发送方)向另一个帐户(接收方)付款。场景如下所示:
- 检查是否
sender.status == 0
,这意味着它已解锁并可以发送付款。 - 查看他的余额中是否
he has more or equals amount of money
他想发送。 - 从他的账户中提取这笔钱。
- 检查是否
receiver.status == 0
,表示已解锁,可以收钱 - 在收款人账户上存入金额。
- 将付款状态更改为1,即成功。
这个场景告诉我们使用两个 DAO 实例:AccountDao
和 PaymentDao
并从这些实例调用方法。当我在 PaymentService
中实现这个场景时,它是实现事务的正确方法吗?
由于您没有使用某些框架,例如 Spring Transaction(我强烈建议您使用),我建议您执行以下操作:
- 只使用一个 DAO class 来创建您需要的所有业务流程并在那里使用交易。
- 在服务层创建连接,并将其作为参数传递给您在业务流程中需要的所有 DAO。我不喜欢这种方式,因为您会将连接控制委托给服务层,而不是数据访问层。
- 将 JDBC 更改为使用 Spring Transaction,这将允许您注释将在服务层中的同一事务中的方法,尽管它们位于不同的 DAO 中。这是可行的,因为 Spring 将控制连接,因此它将通过 DAO 注入相同的连接。看看这个 例子
更多的是设计偏好问题,然后才是正确的