Hibernate 在合并JPA实体之前,Bean验证不起作用

Hibernate 在合并JPA实体之前,Bean验证不起作用,hibernate,jsf,jpa,bean-validation,wildfly,Hibernate,Jsf,Jpa,Bean Validation,Wildfly,当Facelet的后台bean调用setLastName(“Test!!!”)时,不会抛出ConstraintViolationException,尽管方法参数中明显存在非alpha字符 我设置了一个断点来验证setLastName是否被调用,并观察到JPA实体的lastName值发生了变化。验证应该立即失败,是吗?不是 稍后,当调用EntityManager#merge时,当需要持久化更改时,将抛出ConstraintViolationException 约束冲突列表:[ Constraint

当Facelet的后台bean调用
setLastName(“Test!!!”)
时,不会抛出ConstraintViolationException,尽管方法参数中明显存在非alpha字符

我设置了一个断点来验证setLastName是否被调用,并观察到JPA实体的lastName值发生了变化。验证应该立即失败,是吗?不是

稍后,当调用EntityManager#merge时,当需要持久化更改时,将抛出ConstraintViolationException

约束冲突列表:[ ConstraintViolationImpl{interpolatedMessage='error.spacesandletters', propertyPath=lastName,rootBeanClass=class foo.bar.business.model.entity.authenticate.User, messageTemplate='error.spacesandletters'}]

所以我知道验证是可用的,并且它正在JPA pre-persist中工作。但由于某些原因,它在第一次通过支持bean调用User#setLastName时不起作用。我做错了什么

编辑#1:

我应该提到,我的ChangePasswordBean可以很好地与以下两个自定义注释配合使用

@NotEmpty @Password private String password1;
@NotEmpty @Password private String password2;
但在本例中,支持bean的字段被注释。而在上面的示例中,支持bean指向其getter被注释的JPA实体

编辑#2:

在阅读了BalusC的参考资料后,他认为问题可能与升级到Mojarra 2.2.8-01的I有关。以下是Wildfly启动日志中的条目:

17:41:51965信息[org.jboss.as.jsf](服务器服务线程池--38)JBAS012615:激活了以下jsf实现:[mojarra-2.2.8-01,main]


不幸的是,我描述的问题并没有消失。JPA实体上的Bean验证注释不起作用,而JSF托管Bean上的Bean验证注释起作用。

这是正确的行为。如果您依赖基于JPA事件的验证,则验证将在更新前事件发生。没有可在单个字段更改时触发的生命周期事件。实际上,这只适用于插入指令的类,因为否则甚至无法截取值的设置。此外,Bean验证的核心是一个验证整个Bean及其关联的框架。因此,即使在
Validation
API中存在
validateValue
validateProperty
,主要的验证例程是
validate
,它将bean/对象作为参数

所以要回答你的问题:

验证应该立即失败,是吗

不,不应该


在调用setter时确实需要直接验证吗?有很多方法可以做到这一点,但这需要编写一些自定义代码,您可能需要使用编译或运行时拦截框架

只是一个粗略的猜测——将注释从get移动到set(甚至更好地移动到字段本身)会改变什么吗?如果您的控制器中没有@Validation,验证只会发生在Persist/Merge级别。我不熟悉Facelet和JSF,但在验证方面应该与SpringMVC有一些相似之处。@pmp:@validation?javax.validation.constraints中没有这样的东西。另外,我没有使用Spring。@Deltharis无法在getter上添加注释;这违反了Bean验证规范。移动到字段本身最好不要更改任何内容,否则规范没有被容器遵循。哪个Mojarra版本?哪个容器impl/version?你在使用JRebel吗?在任何情况下,这可能是一个重复:是的,当用户单击按钮时需要验证——而不是稍后,当实体合并时。调用支持bean的setter时,应抛出ConstraintViolationException。这在我的其他页面上都很好。区别在于这个特定的支持bean指向一个JPA实体。因此,支持bean的getter/setter调用实体bean上的getter/setter。你是说我应该使用两组相同的注释,一组在实体bean上,另一组在支持bean上?我已经用其他信息编辑了我的问题。另一个字段带有注释的支持bean验证得很好,而指向JPA的支持bean有问题。我知道你回答了这个问题,而OP没有使用
[jsf]
标记,但OP明确告诉他使用了Facelets。JSF确实内置了在验证阶段执行Bean验证的支持,正如OP所期望的那样。因此,您的答案从根本上是错误的,您应该修改或删除它。
@NotEmpty @Password private String password1;
@NotEmpty @Password private String password2;