我目前正在重构已使用JPA的应用程序,但JPA EnitytManager
(和事务)当前的作用域为DAO层。还有一个存储库层和一个服务层。我想使服务层成为事务性的,并且在服务层上每个请求有一个EntityManger
。理想情况下,我不希望我的服务或存储库层知道关于JPA的任何信息。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实例兼容,如果实体不验证,它也会引发异常。
新的代码选项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
。我不确定这是否是一种非常干净的方法。
你对此有何看法?