课程:1. 入门教学 |
2. 基本域模型(上) |
3. 基本域模型(下) |
4. 优化用户界面 |
5. 敏捷开发 |
6. 映射式超类继承 |
7. 实体继承 |
8. 视图继承(View) |
9. Java 属性 |
10. 计算属性 |
11. 用在集合的 @DefaultValueCalculator |
12. @Calculation 和集合总计 |
13. 从外部文件的 @DefaultValueCalculator |
14. 手动更改 schema |
15. 多用户时默认值的计算 |
16. 同步持久属性和计算属性 |
17. 从数据库中的逻辑 |
18. 使用 @EntityValidator 进行验证 |
19. 验证替代方案 |
20. 删除时验证 |
21. 自定义 Bean Validation 注解 |
22. 在验证中调用 REST 服务 |
23. 注解中的属性 |
24. 改进标准行为 |
25. 行为与业务逻辑 |
26. 参照与集合 |
A. Architecture & philosophy |
B. Java Persistence API |
C. Annotations |
D. Automated testing
在上一章,我们学到在保存时验证的替代方案。在本章,我们将研究在删除时的验证。
删除时使用 @RemoveValidator 验证
到目前为止我们所看到的验证都是在实体被修改时执行的,但有时在需要删除实体之前执行验证,并使用它来取消实体删除。
我们将修改应用程序,当订单有关联的发票时会拒绝删除订单。要实现这一点,得用 @RemoveValidator 注解 Order 实体,如下:
@RemoveValidator(com.yourcompany.invoicing.validators.OrderRemoveValidator.class) // 带有验证的类
public class Order extends CommercialDocument {
现现在,在删除订单之前,会执行 OrderRemoveValidator 中的逻辑,如果验证失败,则不会删除订单。我们看看验证器的代码:
package com.yourcompany.invoicing.validators; // 在验证器包
import com.yourcompany.invoicing.model.*;
import org.openxava.util.*;
import org.openxava.validators.*;
public class OrderRemoveValidator
implements IRemoveValidator { // 必须实现 IRemoveValidator
private Order order;
public void setEntity(Object entity) // 在验证之前将使用此方法注入要移除的实体
throws Exception
{
this.order = (Order) entity;
}
public void validate(Messages errors) // 验证逻辑
throws Exception
{
if (order.getInvoice() != null) {
// 通过在errors添加消息,验证将失败並而中止刪除
errors.add("cannot_delete_order_with_invoice");
}
}
}
验证的逻辑在 validate() 方法中。在调用它之前,要验证的实体会使用 setEntity() 注入。如果在 errors 中添加消息,则验证将失败并且实体不会被删除。您必须在 invoicing/src/main/resources/i18n/invoicing-messages_zh.properties 文件中添加:
cannot_delete_order_with_invoice=无法删除带有发票的订单
如果您现在尝试删除带有关联发票的订单,您将收到一条错误消息,并且不会删除。
如您所见,使用 @RemoveValidator 并不难,但很冗长。您必须编写一个全新的类来添加一个简单的 if。现在让我们研究一个更简短的替代方案
删除时使用 JPA 回调方法验证
我们将尝试用另一种更简单的方法来执行删除时的验证,只需将验证逻辑从验证器类移动到 Order 实体,在本例中为 @PreRemove 方法。
首先,从您的项目中删除 OrderRemoveValidator 类。还要从您的 Order 实体中删除 @RemoveValidator 注解:
//@RemoveValidator(com.yourcompany.invoicing.validators.OrderRemoveValidator.class) // 删除 @RemoveValidator
public class Order extends CommercialDocument {
我们刚刚把验证删除了。现在我们再次添加此功能,但现在是在 Order 类中添加 validateOnRemove() 方法:
@PreRemove // 在删除实体前
private void validateOnRemove() {
if (invoice != null) { // 验证逻辑
throw new javax.validation.ValidationException( // 抛出运行时异常
XavaResources.getString( // 並获取消息
"cannot_delete_order_with_invoice"));
}
}
此验证将在删除订单之前执行。如果失败,则会抛出 ValidationException。您可以抛出任何运行时异常以中止删除。只需在实体中添加一个方法就能实行验证了。
哪一个是最佳的验证方法?
您已经学到了几种在模型类中进行验证的方法。至于哪一个是最好的?它们都是最佳的选项。因为这取决于您面对的情况和个人喜好。如果您有一个重要且可在整个应用程序中重复使用的验证,那么使用 @EntityValidator 和 @RemoveValidator 是一个不错的选择。另一方面,如果你想在 OpenXava 之外使用你的模型类而不使用 JPA,那么在 setter 中使用验证会更好。
在我们的示例中,我们使用 @AssertTrue 进行"订单须已送达才能添加至发票中"的验证,并使用 @PreRemove 进行删除时的验证,因为这是最简单的方案。
总结
在本章,您学到了几种在 OpenXava 应用程序中进行验证的方法。在下一章,您将学习如何创建自定义的 Bean Validation。这会非常有用!