我正在使用JPA 2.0/Hibernate验证来验证我的模型.我现在有一种情况,必须验证两个字段的组合:
public class MyModel {
public Integer getValue1() {
//...
}
public String getValue2() {
//...
}
}
Run Code Online (Sandbox Code Playgroud)
该模型是无效的,如果这两个getValue1()和getValue2()的null和有效的,否则.
如何使用JPA 2.0/Hibernate执行此类验证?使用简单的@NotNull注释,两个getter都必须为非null才能通过验证.
我想用JSR-303做一点自定义验证javax.validation.
我有一个领域.如果在此字段中输入了某个值,我想要求其他几个字段不是null.
我想弄清楚这一点.不确定我会称之为什么来帮助找到解释.
任何帮助,将不胜感激.我对此很新.
目前我正在考虑自定义约束.但我不确定如何从注释中测试依赖字段的值.基本上我不确定如何从注释访问面板对象.
public class StatusValidator implements ConstraintValidator<NotNull, String> {
@Override
public void initialize(NotNull constraintAnnotation) {}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if ("Canceled".equals(panel.status.getValue())) {
if (value != null) {
return true;
}
} else {
return false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是panel.status.getValue();给我带来麻烦..不知道如何实现这一目标.
java.lang.annotation.ElementType:
程序元素类型.此枚举类型的常量提供Java程序中声明的元素的简单分类.这些常量与Target元注释类型一起使用,以指定使用注释类型的合法位置.
有以下常量:
有人可以解释它们中的每一个(在实际代码中它们会被注释)吗?
根据我的知识:
PUT - 用其整个表示更新对象(替换)PATCH - 仅使用给定字段更新对象(更新)我正在使用Spring来实现一个非常简单的HTTP服务器.当用户想要更新他的数据时,他需要将HTTP PATCH发送到某个端点(比方说:) api/user.他的请求体被映射到DTO via @RequestBody,如下所示:
class PatchUserRequest {
@Email
@Length(min = 5, max = 50)
var email: String? = null
@Length(max = 100)
var name: String? = null
...
}
Run Code Online (Sandbox Code Playgroud)
然后我使用这个类的对象来更新(补丁)用户对象:
fun patchWithRequest(userRequest: PatchUserRequest) {
if (!userRequest.email.isNullOrEmpty()) {
email = userRequest.email!!
}
if (!userRequest.name.isNullOrEmpty()) {
name = userRequest.name
}
...
}
Run Code Online (Sandbox Code Playgroud)
我的疑问是:如果客户(例如网络应用程序)想清除房产怎么办?我会忽略这样的改变.
我怎么知道,如果用户想要清除一个属性(他故意将我命名为null)或者他只是不想改变它?在两种情况下,它在我的对象中都是null.
我可以在这里看到两个选项:
@Valid现在用.如何妥善处理此类案件,与REST和所有良好做法保持一致?
编辑:
可以说不PATCH应该在这样的例子中使用,我应该PUT用来更新我的用户.但是模型更改怎么样(例如添加新属性)?每次用户更改后,我都必须对我的API(或单独的用户端点)进行版本控制.例如,我将有api/v1/user终点,它接受PUT一个老请求主体和api/v2/user …
我们都知道,Spring MVC通常与Hibernate Validator和JSR-303很好地集成.但正如有人所说,Hibernate Validator只适用于Bean Validation,这意味着应该将更复杂的验证推送到数据层.此类验证的示例:业务密钥唯一性,内部记录依赖性(通常指向数据库设计问题,但我们都生活在一个不完美的世界).即使像字符串字段长度这样的简单验证也可能由某个DB值驱动,这使得Hibernate Validator无法使用.
所以我的问题是,Spring或Hibernate或JSR是否提供了执行此类复杂验证的功能?是否有一些已建立的模式或技术部分可以在基于Spring和Hibernate的标准Controller-Service-Repository设置中执行此类验证?
更新:让我更具体一点.例如,有一个表单向控制器的save方法发送AJAX保存请求.如果出现一些验证错误 - 简单或"复杂" - 我们应该回到浏览器,其中一些json指示有问题的字段和相关错误.对于简单错误,我可以从中提取字段(如果有)和错误消息BindingResult.您会针对"复杂"错误提出什么样的基础设施(可能是特定的,而不是临时的例外?)?使用异常处理程序对我来说似乎不是一个好主意,因为在save方法之间分离单个验证过程@ExceptionHandler并使事情变得复杂.目前我使用一些特殊的例外(如,ValidationException):
public @ResponseBody Result save(@Valid Entity entity, BindingResult errors) {
Result r = new Result();
if (errors.hasErrors()) {
r.setStatus(Result.VALIDATION_ERROR);
// ...
} else {
try {
dao.save(entity);
r.setStatus(Result.SUCCESS);
} except (ValidationException e) {
r.setStatus(Result.VALIDATION_ERROR);
r.setText(e.getMessage());
}
}
return r;
}
Run Code Online (Sandbox Code Playgroud)
你能提供更优化的方法吗?
我必须使用哪些注释来进行Hibernate验证,以验证要应用于以下内容的String:
//should always have trimmed length = 6, only digits, only positive number
@NotEmpty
@Size(min = 6, max = 6)
public String getNumber {
return number.trim();
}
Run Code Online (Sandbox Code Playgroud)
如何应用数字验证?我会@Digits(fraction = 0, integer = 6)在这里使用吗?
我正在使用此答案中HibernateValidator指定的表格上的两个字段"password"和"confirmPassword"进行验证.以下是约束描述符(验证器接口).
package constraintdescriptor;
import constraintvalidator.FieldMatchValidator;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;
@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = FieldMatchValidator.class)
@Documented
public @interface FieldMatch
{
String message() default "{constraintdescriptor.fieldmatch}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
/**
* @return The first field
*/
String first();
/**
* @return The second field
*/
String second();
/**
* Defines several <code>@FieldMatch</code> annotations on the …Run Code Online (Sandbox Code Playgroud) 这是代码味道,还是以Spring形式实现跨字段验证的最佳方式?
@FieldRequiredIf.List({
@FieldRequiredIf(ifField="firstHomePhoneNumber", matches={EMPTY, NULL},require ="firstMobilePhoneNumber",elseDisplay = "FieldRequiredIf.correspondenceDetailsForm.firstMobilePhoneNumber",groups=FirstLife.class),
@FieldRequiredIf(ifField="secondHomePhoneNumber", matches={EMPTY,NULL},require ="secondMobilePhoneNumber",elseDisplay = "FieldRequiredIf.correspondenceDetailsForm.secondMobilePhoneNumber",groups=SecondLife.class),
@FieldRequiredIf(ifField="lifeAssuredIsPolicyOwner", matches={FALSE},require ="policyOwnerName",elseDisplay = "FieldRequiredIf.correspondenceDetailsForm.policyOwnerName"),
@FieldRequiredIf(ifField="lifeAssuredIsPolicyOwner", matches={FALSE},require ="policyOwnerAddress",elseDisplay = "FieldRequiredIf.correspondenceDetailsForm.policyOwnerAddress"),
@FieldRequiredIf(ifField="insurableInterest", matches={InsurableInterestConstants.OTHER},require ="insurableInterestReason",elseDisplay = "FieldRequiredIf.correspondenceDetailsForm.insurableInterestReason",groups = NonSingleNonMortgage.class),
@FieldRequiredIf(ifField="firstAddress2", matches={NOT_EMPTY},require ="firstAddress1",elseDisplay = "FieldRequiredIf.correspondenceDetailsForm.firstAddress1",groups=FirstLife.class),
@FieldRequiredIf(ifField="firstAddress3", matches={NOT_EMPTY},require ="firstAddress2",elseDisplay = "FieldRequiredIf.correspondenceDetailsForm.firstAddress2",groups=FirstLife.class),
@FieldRequiredIf(ifField="firstAddress4", matches={NOT_EMPTY},require ="firstAddress3",elseDisplay = "FieldRequiredIf.correspondenceDetailsForm.firstAddress3",groups=FirstLife.class),
@FieldRequiredIf(ifField="firstAddress5", matches={NOT_EMPTY},require ="firstAddress4",elseDisplay = "FieldRequiredIf.correspondenceDetailsForm.firstAddress4",groups=FirstLife.class),
@FieldRequiredIf(ifField="secondAddress2", matches={NOT_EMPTY},require ="secondAddress1",elseDisplay = "FieldRequiredIf.correspondenceDetailsForm.secondAddress1",groups=SecondLife.class),
@FieldRequiredIf(ifField="secondAddress3", matches={NOT_EMPTY},require ="secondAddress2",elseDisplay = "FieldRequiredIf.correspondenceDetailsForm.secondAddress2",groups=SecondLife.class),
@FieldRequiredIf(ifField="secondAddress4", matches={NOT_EMPTY},require ="secondAddress3",elseDisplay = "FieldRequiredIf.correspondenceDetailsForm.secondAddress3",groups=SecondLife.class),
@FieldRequiredIf(ifField="secondAddress5", matches={NOT_EMPTY},require ="secondAddress4",elseDisplay = "FieldRequiredIf.correspondenceDetailsForm.secondAddress4",groups=SecondLife.class)
})
public class CorrespondenceDetailsForm {
...
}
Run Code Online (Sandbox Code Playgroud)
为了简化上述操作,我开始将这些列出的注释的几个逻辑组重构为单个自定义注释:(@ FirstLifeContactDetailsObserver和@SecondLifeContactDetailsObserver).这是重构的类级别注释: …
在我的Spring 3 MVC应用程序中,用户需要保存密码,如果他们也能够在保存时确认密码,那将是一个很好的功能.
在bean我使用基于注释的验证.是否有可用于执行此检查的注释验证器?
经过一些谷歌搜索后,我找到了这个博客:http://gochev.blogspot.com/2010/06/spring-mvc-spring-bean-validation.html.但我想我在这里缺少一个jar-lib,因为Eclipse无法找到/建议任何罐子.有人知道我需要什么罐子来工作吗?
提前致谢 :)
首先,让我解释一下,我使用的是Spring MVC 3.1.1和Hibernate验证4.2.0.我在Spring应用程序中使用各种表单的验证注释.由于我的应用程序需要本地化,我一直在使用资源包来查看我的验证消息:
# ValidationMessages.bundle
FieldMatch=Password and confirmation must match.
Run Code Online (Sandbox Code Playgroud)
此消息的相应类定义如下所示:
@FieldMatch.List({
@FieldMatch(first = "password", second = "passwordConfirmation")
})
public class RegistrationForm {
// ...
}
Run Code Online (Sandbox Code Playgroud)
我在appContext.xml中设置了这个自定义资源包,我的消息显示在表单上没有任何问题.
然而,这是我的困境.有一项新要求,我必须确认更多字段匹配.现在我只是确认两个密码字段匹配.现在我的要求是我必须确认电子邮件地址.我知道这是一个愚蠢的要求,但我不能改变它.所以现在类定义将如下所示:
@FieldMatch.List({
@FieldMatch(first = "password", second = "passwordConfirmation")
@FieldMatch(first = "email", second = "emailConfirmation")
})
public class RegistrationForm {
// ...
}
Run Code Online (Sandbox Code Playgroud)
显然,我当前的资源包不起作用,因为我需要两个单独的消息(每个匹配一个).我已尝试使用message="{emails.must.match}"然后在资源包中定义该消息,但它实际上从未显示消息,它只显示实际文本{email.must.match}.
所以解释之后,我的问题很简单:如何让FieldMatch类级别的每个验证器都有一个在资源包中定义的不同消息,以便它可以被本地化?
在此先感谢您的帮助!
[编辑]对于那些好奇的人,这是FieldMatch我正在使用的验证器.
更新5/23/2012 这是其他人要求的bean定义:
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>ErrorBundle</value>
<value>ForgotPasswordBundle</value>
<!-- etc etc -->
</list>
</property>
</bean> …Run Code Online (Sandbox Code Playgroud) java ×8
spring-mvc ×5
annotations ×3
spring ×3
validation ×3
forms ×1
jpa ×1
jpa-2.0 ×1
jsp ×1
kotlin ×1
patch ×1
rest ×1
spring-boot ×1