【问题标题】:Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'prePersist'在回调事件上执行自动 Bean 验证时违反了 Bean 验证约束:'prePersist'
【发布时间】:2012-10-10 15:28:02
【问题描述】:

我想存储birthdate,所以我在 MySQL 中选择了date,当我基于我的数据库创建实体时,结果是这样的:

import java.util.Date;

    // ..code
    @NotNull(message="fill you birthdate")
    @Temporal(TemporalType.DATE)
    private Date birthdate;

但是当我尝试坚持时,它给了我这个错误:

在回调事件:'prePersist' 上执行自动 Bean 验证时违反了 Bean 验证约束。有关详细信息,请参阅嵌入式 ConstraintViolations。

我在这里做错了什么? 我正在阅读有关在 Google 中定义时区的内容,我来自巴西,我该怎么做?

编辑

package entity;

import java.io.Serializable;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.Email;

import java.util.Date;
import java.util.List;


/**
 * The persistent class for the user database table.
 * 
 */
@Entity
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;

    @Temporal(TemporalType.DATE)
    private Date birthdate;

    @NotNull(message="informe seu e-mail")
    @Email(message="e-mail inválido")
    private String email;

    @NotNull(message="informe seu gênero")
    private String gender;

    private String image;

    @NotNull(message="informe seu nome completo")
    private String name;

    @Size(min=6,max=16, message="senha com no mínimo: 6 dígitos e no máximo 16 dígitos")
    @NotNull(message="informe sua senha")
    private String password;

    //bi-directional many-to-one association to Document
    @OneToMany(mappedBy="user")
    private List<Document> documents;

    //bi-directional many-to-one association to QuestionQuery
    @OneToMany(mappedBy="user")
    private List<QuestionQuery> questionQueries;

    //bi-directional many-to-one association to Team
    @OneToMany(mappedBy="user")
    private List<Team> teams;

    public User() {
    }

    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Date getBirthdate() {
        return this.birthdate;
    }

    public void setBirthdate(Date birthdate) {
        this.birthdate = birthdate;
    }

    public String getEmail() {
        return this.email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getGender() {
        return this.gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getImage() {
        return this.image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public List<Document> getDocuments() {
        return this.documents;
    }

    public void setDocuments(List<Document> documents) {
        this.documents = documents;
    }

    public List<QuestionQuery> getQuestionQueries() {
        return this.questionQueries;
    }

    public void setQuestionQueries(List<QuestionQuery> questionQueries) {
        this.questionQueries = questionQueries;
    }

    public List<Team> getTeams() {
        return this.teams;
    }

    public void setTeams(List<Team> teams) {
        this.teams = teams;
    }

    public void print() {
        System.out.println("User [id=" + id + ", birthdate=" + birthdate + ", email="
                + email + ", gender=" + gender + ", image=" + image + ", name="
                + name + ", password=" + password + "]");
    }



}

【问题讨论】:

  • 您的实体代码中有@PrePersist 吗?如果是这样,请也粘贴它
  • 这是一个非常烦人的异常,因为我以前从未遇到过Date 的任何问题..
  • 这是一个非常普遍的错误,它可能会出现在模型的其他一些字段上的验证错误。我常用的方法是:启用 SQL 和参数日志记录(对于 EclipseLink 来说很容易,但我认为大多数 JPA 提供商都支持它)或发出 try/catch em.flush()(强制提交而不是等待容器提交)并循环 ConstraintViolations为了找到问题。
  • 为了从 JPA 用户那里获得更好的答案,请提及 JPA impl/version、DB server vendor/version 和使用的 JDBC 驱动程序版本。您的第一步是尝试使用 &lt;property name="javax.persistence.validation.mode" value="none" /&gt; 禁用 persistence.xml 中的 bean 验证@

标签: jpa jpa-2.0 bean-validation


【解决方案1】:

我遇到了同样的问题,但经过数小时寻找答案后,我终于找到了....您应该编辑您的 AbstractFacade.java 类并添加这个代码

public void create(T entity) {

    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Validator validator = factory.getValidator();
    Set<ConstraintViolation<T>> constraintViolations = validator.validate(entity);
    if(constraintViolations.size() > 0){
        Iterator<ConstraintViolation<T>> iterator = constraintViolations.iterator();
        while(iterator.hasNext()){
            ConstraintViolation<T> cv = iterator.next();
            System.err.println(cv.getRootBeanClass().getName()+"."+cv.getPropertyPath() + " " +cv.getMessage());

            JsfUtil.addErrorMessage(cv.getRootBeanClass().getSimpleName()+"."+cv.getPropertyPath() + " " +cv.getMessage());
        }
    }else{
        getEntityManager().persist(entity);
    }
}

现在,此方法将提醒您哪个属性以及验证失败的原因。 我希望这对你有用,就像对我一样。

【讨论】:

  • 在哪里可以找到 AbstractFacade.java 类?我应该开设一个新课程吗?
【解决方案2】:

我有一个捷径,在你持久化实体的地方捕获以下异常。在我的例子中,它在 EJB add 方法中。我在哪里em.persist()。然后检查服务器日志,您将看到哪个属性违反了约束。

catch (ConstraintViolationException e) {
       log.log(Level.SEVERE,"Exception: ");
       e.getConstraintViolations().forEach(err->log.log(Level.SEVERE,err.toString()));
    }

【讨论】:

    【解决方案3】:

    错误显示您尝试保留的实体失败 数据库约束,因此请在实际插入之前尝试确定要插入数据库的确切值。

    并通过评论/省略@NotNull 注释来尝试。

    【讨论】:

    • 这就是我在数据库中编写表单的方式:User [id=null, birthdate=Sun Sep 29 21:00:00 BRT 1985, email=valter@brainset.com.br, gender=M, image=null, name=valter, password=afSQtkcfmikK2G7CLfcL4RJewIGB10oe
    • 还是一样的异常
    • 你的主键是什么id?
    • 如果你的主键是id,你怎么设置成null
    • id 不能为 null 尝试找出它为什么为 null?
    【解决方案4】:

    我解决问题的方法是将@Size@NotNull 的顺序颠倒了

    之前:

    @Size(min=6,max=16, message="senha com no mínimo: 6 dígitos e no máximo 16 dígitos")
    @NotNull(message="informe sua senha")
    private String password;
    

    之后:

    @NotNull(message="informe sua senha")
    @Size(min=6,max=16, message="senha com no mínimo: 6 dígitos e no máximo 16 dígitos")
    private String password;
    

    我不知道为什么这个顺序如此重要,但确实如此 =] 谢谢大家!

    【讨论】:

    • 我刚遇到同样的问题,这篇文章对我有帮助!我解决了它删除@NotNull并将nullable = false放入@Column
    【解决方案5】:

    当然,Iomanip 的回答是完全正确的!我只是将其扩展了一点。也许这也有帮助:

      private boolean constraintValidationsDetected(T entity) {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(entity);
        if (constraintViolations.size() > 0) {
          Iterator<ConstraintViolation<T>> iterator = constraintViolations.iterator();
          while (iterator.hasNext()) {
            ConstraintViolation<T> cv = iterator.next();
            System.err.println(cv.getRootBeanClass().getName() + "." + cv.getPropertyPath() + " " + cv.getMessage());
    
            JsfUtil.addErrorMessage(cv.getRootBeanClass().getSimpleName() + "." + cv.getPropertyPath() + " " + cv.getMessage());
          }
          return true;
        }
        else {
          return false;
        }
      }
    
      public void create(T entity) {
        if (!constraintValidationsDetected(entity)) {
          getEntityManager().persist(entity);
        }
      }
    
      public T edit(T entity) {
        if (!constraintValidationsDetected(entity)) {
          return getEntityManager().merge(entity);
        }
        else {
          return entity;
        }
      }
    
      public void remove(T entity) {
        if (!constraintValidationsDetected(entity)) {
          getEntityManager().remove(getEntityManager().merge(entity));
        }
      }
    

    【讨论】:

    • 感谢您的代码,它运行良好。我猜方法名有错别字:constraintValidationsDetected -> constraintViolationsDetected
    • 在您必须删除之前可以正常工作。它在合并和删除之间的循环中导致 StackOverflowError。我必须禁用 remove 方法才能使其工作。
    【解决方案6】:

    当我试图持久化一个实体时,我花了几个小时来解决这个错误。

    Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'preUpdate'. Please refer to embedded ConstraintViolations for details.
    

    这个错误信息没有帮助,相当混乱……

    无论如何,在我的情况下,错误的原因是 - Enity 中的注释之间的差异

    @Size(min = 1, max = 10)
    @Column(name = Utilizator.JPA_DISCRIMINATOR)
    private String jpaDiscriminator;
    

    以及DataBase列定义:

    jpaDiscriminatorVARCHAR(15) 非空,

    【讨论】:

      【解决方案7】:

      我有类似的问题。在我的情况下,引用的 PK 和 FK 的大小不同(参见示例)。

      实体 A:

      some_pk   INTEGER NOT NULL,
      fk_b      VARCHAR2(5 CHAR)
      ...
      

      fk_b 引用实体 B 的 ID 字段

      实体 B:

      id VARCHAR2(4 CHAR)
      ...
      

      id 在这里是一个 PK。

      注意 ID(4) 和 FK_B(5) 的大小。将 B 的 ID 更改为 5 CHAR 后,错误消失了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-30
        • 2015-12-29
        相关资源
        最近更新 更多