这是我之前问题的扩展。我实现了Dennis R的答案,并且正在使用hibernate-validator
。有没有办法要求在json请求中指定一个或另一个字段,但不能同时指定两个?从我之前的帖子中,在Request类中,我希望用户传入id或代码,但不能同时传入。
我发现这个资源对我来说可能是正确的解决方案,但我不完全理解那里发生了什么,为什么它有效,坦率地说,它看起来太冗长了。这是唯一的方法吗?
您可以使用Group作为替代方案。例如,这是请求。java:
public class Request {
public interface IdOrCodeValidationGroup {}
@NotNull
@NotEmpty
private String id;
@Digits(integer=4, fraction=0)
private double code;
@NotNull
@NotEmpty
private String name;
@AssertTrue(groups = IdOrCodeValidationGroup.class)
private boolean idOrCodeFilled;
public Request(String id, double code, String name) {
this.id = id;
this.code = code;
this.name = name;
}
public boolean isIdOrCodeFilled() {
if (id == null && code > 0) {
idOrCodeFilled = true;
} else if (id != null && code == 0) {
idOrCodeFilled = true;
} else idOrCodeFilled = false;
return idOrCodeFilled;
}
}
然后像这样使用验证器:
@Test
public void testValidation() {
// Of course all of this valid. No group at all.
final Request request = new Request("ID-001", 111, "Data 1");
final Set<ConstraintViolation<Request>> fails = this.validator.validate(request);
Assert.assertTrue(fails.isEmpty());
}
@Test
public void testValidationWithGroup() {
// We use "IdOrCodeValidationGroup.class" group, thus this is invalid.
Request request = new Request("ID-001", 111, "Data 1");
Set<ConstraintViolation<Request>> fails = this.validator.validate(request, IdOrCodeValidationGroup.class);
Assert.assertFalse(fails.isEmpty());
// Lets make one of constraint true; In this case, we set code = 0.
request = new Request("ID-002", 0, "Data 2");
fails = this.validator.validate(request, IdOrCodeValidationGroup.class);
// Passed!
Assert.assertFalse(fails.isEmpty());
}
下面是功能完整的示例代码。(别忘了结帐“so-36365734”分行)。这是关于Bean验证组的官方文档。
HTH。
天哪在我看来,这些链接的参考文献过于复杂。存在注释:
@org.hibernate.annotations.Check
我经常遇到同样的情况,我想执行这种类型的验证,我有一个或另一个字段,或者我有两个或两个都没有。。。
@Entity
@org.hibernate.annotations.Check(constraints = "(field1 IS NULL OR field2 IS NULL) AND (field1 IS NOT NULL OR field2 IS NOT NULL)")
public class MyEntity{
String field1;
Double field2;
}
这将在数据库中创建一个检查约束,该约束将强制执行该约束。它将验证从Hibernate和您的代码转移到数据库(这也将防止任何在您的hibernate配置之外访问您的数据库的应用程序破坏此约束)。
此注释的创建不会自动在您的数据库上执行约束的创建,但如果/当您创建约束时,它也会通知hibernate它。
在Postgres中,该约束类似于:ALTER TABLE my\u entity ADD constraint my\u entity\u check check((field1为NULL或field2为NULL)和(field1不为NULL或field2不为NULL));
Postgres检查约束
Oracle检查约束
如果您无法生成精确的SQL,请创建注释,然后允许hibernate针对空数据库自动生成数据库模式,它将向您显示正确的SQL。但是有了注释,hibernate也知道约束,因此如果您允许hibernate为任何自动化测试等生成模式,则可以自动生成...
正如我之前评论的那样,在这里遵循Nicko的回答,您可以使用以下代码实现您想要的:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = FieldMatchValidator.class)
public @interface FieldMatch {
String message() default "something is wrong!";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
/**
* @return The first field
*/
String first();
/**
* @return The second field
*/
String second();
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface List {
FieldMatch[] value();
}
public static class FieldMatchValidator implements ConstraintValidator<FieldMatch, Object> {
private String firstFieldName;
private String secondFieldName;
@Override
public void initialize(FieldMatch fieldMatch) {
firstFieldName = fieldMatch.first();
secondFieldName = fieldMatch.second();
}
public boolean isValid(Object object, ConstraintValidatorContext constraintContext) {
try {
final Object firstObj = getProperty(object, firstFieldName);
final Object secondObj = getProperty(object, secondFieldName);
if(firstObj == null && secondObj == null || firstObj != null && secondObj != null) {
return false;
}
} catch (final Exception ignore) {
// ignore
}
return true;
}
private Object getProperty(Object value, String fieldName) {
Field[] fields = value.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.getName().equals(fieldName)) {
field.setAccessible(true);
try {
return field.get(value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return null;
}
}
}
用法:
@FieldMatch.List({
@FieldMatch(first = "name", second = "people"),
@FieldMatch(first = "age", second = "abc")
})
public class Foo {
private String name;
private List<String> people;
private int age;
private Boolean abc;
}
唯一的区别是,您不想检查内容是否相等,只要一个字段为空,另一个字段不为空。
编辑:
要按照注释的要求在ExceptionHandler上获取对象,只需将异常包装在自定义异常周围,并在抛出时传递对象,即:
public class CustomException extends Exception {
private String message;
private Object model;
public CustomException(String message, Object model) {
super(message);
this.model = model;
}
public Object getModel() {
return model;
}
}
有了这个,你可以简单地得到如下结果:
@ExceptionHandler(CustomException.class)
public ModelAndView handleCustomException(CustomException ex) {
Object obj = ex.getModel();
//do whatever you have to
}
问题内容: 我有两个字段,仅当两个字段都不存在时才是可选的: 现在,需要大于。如何包含此过滤器? 问题答案: 有 没有内置的验证 ,它可以让你比较字段值一样,在 Laravel ,所以你需要实现一个 自定义的验证 ,这将让你重新使用验证需要的地方。幸运的是,Laravel使编写自定义验证器 变得非常容易 。 首先在您的 AppServiceProvider中 定义新的验证器: 现在,您可以在 $
我使用Symfony 5.3。我有一个表单,有3个字段没有映射到任何实体: "原因"-文本, use_predefined复选框 "predefined_reason"-下拉列表。 我构建的表单如下(一个片段): “原因”字段应根据需要显示在UI中,但其他两个字段不应显示。但是,在验证过程中,如果选中了复选框“预定义的原因”,则第一个字段不应为必填字段,而“预定义的原因”应为必填字段。
我有一个Spring Boot rest服务,它将调用另一个web服务(用.NET编写),但它需要安装web服务的服务器的公共证书。
晚上好,我正在尝试在下面的场景中使用Hibernate验证器:
我想验证字段,如果存在,将失败,如果另一个字段不存在如何做到这一点?我已经创建了自定义验证,以获得基于存储ID的记录 我有字段和,并且字段根据在最大值和最小值之间进行验证,如果我显示=且未填写字段,则验证字段将通过,并显示错误,因为我未填写我希望在执行自定义验证之前检查是否为空。。 我已经阅读了laravel文档上的所有验证方法,但仍然没有找到解决方案。怎么做?
我的mac电脑中没有internet连接。我需要使用docker pull。我的想法是,我将使用docker拉入我的一台连接互联网的mac电脑,然后将其复制到没有互联网连接的mac电脑上。如何复制?