java - JPA 模型验证和事务处理

标签 java jpa domain-driven-design separation-of-concerns

我目前正在重构一个已经使用 JPA 但 JPA EnitytManager 的应用程序(和交易)目前仅限于 DAO 层。还有一个存储库层和一个服务层。我想让服务层具有事务性,并且有一个 EntityManger每个服务层上的请求。理想情况下,我不希望我的服务层或存储库层知道任何有关 JPA 的信息。

目前,存储库和服务层与它们从 DAO 层获得的分离实体一起工作。对模型进行了更改,实体被合并回 DAO 层。在新结构中,实体在整个请求期间保持托管状态,1 个请求包含在 1 个事务中。更改会在事务结束时自动提交。这似乎更符合 JPA 的精神,并且在最常见的情况下效果很好。

有时会对模型进行更改,然后对模型进行验证。如果模型不再有效,则不应保存更改。在旧结构中,这很简单:

在这个例子中,流程基本上是一个图,整个图都必须验证,没有自引用,每个节点都必须可达,第一个节点有一些特殊要求,需要有一个最终节点,等等。我们首先对模型进行更改,然后验证模型。

旧的存储层代码:

changeProcessModel();
messages = ProcessValidator.validate(process);
if (messages.hasNoErrors()) {
    processDao.merge(process);
    messages.addInfoMessage("Process was updated succesfully");
}
return messages;

在新结构中,我认为我有三个选项,我想知道哪一个被认为是最佳实践,或者是否有任何其他替代方案。

新代码选项 1:

changeProcessModel();
messages = ProcessValidator.validate(process);
if (messages.hasNoErrors()) {
    messages.addInfoMessage("Process was updated succesfully");
} else {
    throw new InvalidProcessException(messages);
}
return messages;

这段代码有点滥用了 RuntimeException用于验证一些业务规则。我不认为这被认为是最佳实践,但事务已回滚。这似乎也与 Bean Validation 兼容,如果实体未通过验证,Bean Validation 也会抛出异常。

新代码选项 2:

changeProcessModel();
messages = ProcessValidator.validate(process);
if (messages.hasNoErrors()) {
    messages.addInfoMessage("Process was updated succesfully");
} else {
    em.getTransactionManager.rollback();
}
return messages;

此代码直接在 JPA 上执行回滚 TransactionManager并在我的存储库层和 JPA 之间引入依赖关系。

新代码选项 3:

changeProcessModel();
messages = ProcessValidator.validate(process);
if (messages.hasNoErrors()) {
    messages.addInfoMessage("Process was updated succesfully");
} else {
    processDao.refresh(process);
}
return messages;

这段代码看起来很不错,但它确实依赖于 CascadeType.REFRESH在需要刷新的流程实体关系上适当设置。

我也可以例如 processDao.clear();processDao.rollback();但这增加了 processDao 的范围。到整个 entityManger .我也不确定这是否是一种非常干净的方法。

你对此有何看法?

最佳答案

我认为您对自己在领域中的持久性了解得越少越好。因此,根据将持久性视为域模型的服务而不是将其视为模型的一部分的想法,我建议采用以下解决方案:

  • 域必须始终处于一致状态;
  • 所以;进入模型的更改(来自服务,您拥有的用户界面)不能在不知道 future 模型得到验证的情况下更改模型。
  • 含义:当前模型始终是一致的。

在公式中:Future model = CurrentModel.PerformChanges().Validated();

如何做到这一点?可能使用工作单元类型的构造。 (http://martinfowler.com/eaaCatalog/unitOfWork.html) 每当更改并验证域对象时,它都会引发一个它已更改的事件。工作单元经理负责获取这些事件,然后确保将这些内容放入数据库中。当更改无法验证时,不会引发事件并且模型被标记为“无效”。因为您在请求隔离模式下工作,所以这不是问题。当您在共享域模型中工作时,更改必须在您的域中回滚!

这可能是解决问题的最学术方法,但也许它有助于开始讨论,在这些情况下该怎么做......

关于java - JPA 模型验证和事务处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8521354/

相关文章:

java - 数组 <?在 Java 中扩展 T>

Java FXML :How to TableCell Edit Column Then reflect to second Column

java - 有什么方法可以用 2 个嵌套循环来加速算法吗?

java - Hibernate JPA find() 和 merge() 之间删除的区别

sql - JPQL 中的空白 FROM 子句?

domain-driven-design - DDD中的数据访问?

java - 树遍历

postgresql - 同一实体的多个表示正在与@OneToMany 合并

domain-driven-design - DDD - 业务决策基于数据库逻辑

c# - gRPC 和域驱动设计 - 在哪里放置 proto 文件(域层与其他地方)?