我创建了下面的实体和嵌入:为什么GlassFish 4不验证我的@Valid @ElementCollection字段的成员?
@Entity
public class Person implements Serializable {
@NotNull
@Pattern(regexp = "([A-Z][a-z]*)*", message = "First Name must match pattern ([A-Z][a-z]*)*")
private String firstName;
@Valid
@ElementCollection
private List<Email> email;
...
}
@Embeddable
public class Email implements Serializable {
@NotNull (message = "Email Address may not be null")
@Pattern(regexp = "[-0-9a-zA-Z.+_][email protected][-0-9a-zA-Z.+_]+.[a-zA-Z]{2,4}", message = "Email Address must match pattern [-0-9a-zA-Z.+_][email protected][-0-9a-zA-Z.+_]+.[a-zA-Z]{2,4}")
private String address;
...
}
然后我用PersonCreater.xhtml JSF页面和的PersonManager无状态会话EJB如下测试GlassFish4/Hibernate验证5.0.0级联验证功能:
- 已创建人员。
- 将“adsj alkjdfa”地址添加到Person邮件列表中。
- 将“#AV @#$ R”地址添加到个人邮件列表中。
- 坚持的对象。
不幸的是,我没有收到任何错误,并且具有无效电子邮件地址的Person对象被持久化到数据库。
作为测试,我将我的Person类中的电子邮件属性从电子邮件列表更改为单个电子邮件,如下所示。
@Entity
public class Person implements Serializable {
@Valid
private Email email;
...
}
然后我进行了以下测试。
- 创建人。
- 将“adsj alkjdfa”地址添加到Person邮件列表中。
- 坚持的对象。
正如预期的那样,我收到一个违反约束条件,说明电子邮件不符合模式,并且Person未保留在数据库中。
作为最终测试,我将以下代码添加到了我的JSF CDI Bean的addEmail方法中,以便手动检查验证。
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<Email>> emailCV = validator.validate(newEmail);
logger.debug("Email constraint violations: " + emailCV);
Set<ConstraintViolation<Person>> personCV = validator.validate(person);
logger.debug("Person constraint violations: " + personCV);
Set<ConstraintViolation<Person>> personEmailCV = validator.validateProperty(person, "email");
logger.debug("Person Email constraint violations: " + personEmailCV);
当我输入了一个无效的电子邮件地址,我收到以下消息:
- 电子邮件约束违规:[{ConstraintViolationImpl = interpolatedMessage“电子邮件地址必须匹配模式...
- 人约束违例:[ConstraintViolationImpl {interpolatedMessage ='电子邮件地址必须匹配模式...
- 人员电子邮件约束违规:[]
我预计validator.validate(newEmail);
方法调用会抛出模式违规,因为我自己验证了newEmail。
但是,我没想到validator.validate(person);
方法调用会发现模式违规,因为我认为我的问题与我的实体和Embeddable类有关。
这些结果告诉我,我已经正确配置了我的Entity和Embeddable类,但由于某些原因,当我使用我的JSF页面创建Person或使用我的EJB持久化Person时,GlassFish不会自动验证电子邮件属性。
我是否需要配置GlassFish以自动执行级联验证?
最后,我不知道为什么validator.validate(person);
方法调用发现模式违规和validator.validateProperty(person, "email");
方法调用没有。
以下是我的persistence.xml中的持久性单元。
<persistence-unit name="ELISPU" transaction-type="JTA">
<jta-data-source>jdbc/elis</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="create" />
</properties>
</persistence-unit>
以下是我的Person类的更完整的视图:
@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@NamedQueries({
@NamedQuery(name = "Person.findAll", query = "SELECT p FROM Person p ORDER BY p.lastName, p.firstName"),
@NamedQuery(name = "Person.findByName", query = "SELECT p FROM Person p WHERE p.lastName = :lastName and p.firstName = :firstName and p.middleName = :middleName"),
@NamedQuery(name = "Person.findByShortName", query = "SELECT p FROM Person p WHERE p.shortName = :shortName") })
public class Person implements Serializable {
final static Logger logger = LoggerFactory.getLogger(Person.class.getName());
static final long serialVersionUID = 1L;
@TableGenerator(name = "Person_Generator", table = "ID_Gen", pkColumnName = "GEN_NAME", valueColumnName = "GEN_VAL", initialValue = 0, allocationSize = 1)
@Id
@GeneratedValue(generator = "Person_Generator")
@XmlAttribute
private Long id;
@Version
@XmlAttribute
private Integer version;
private String prefixName;
@NotNull
@Pattern(regexp = "([A-Z][a-z]*)*", message = "First Name must match pattern ([A-Z][a-z]*)*")
private String firstName;
@Pattern(regexp = "([A-Z][a-z]*)*", message = "Middle Name must match pattern ([A-Z][a-z]*)*")
private String middleName;
@NotNull
@Pattern(regexp = "([A-Z][a-z]*)*", message = "Last Name must match pattern ([A-Z][a-z]*)*")
private String lastName;
private String suffixName;
@NotNull
@Pattern(regexp = "([A-Z][a-z]*)*", message = "Familiar Name must match pattern ([A-Z][a-z]*)*")
private String familiarName;
@NotNull
@Column(unique = true)
@Pattern(regexp = "[a-z0-9]*", message = "Short Name must match pattern [a-z0-9]*")
private String shortName;
private String description;
@Valid
@ElementCollection
private List<Email> email;
@ElementCollection
private List<Voice> voice;
@ElementCollection
private List<Address> addresses;
private ELISFile picture;
@XmlElementWrapper(name = "notes")
@XmlElement(name = "note")
@ElementCollection
private List<EntityNote> notes;
@XmlTransient
// @XmlElementWrapper(name="history")
// @XmlElement(name="event")
@NotNull
@ElementCollection
private List<EntityEvent> history;
public Person() {
logger.debug("Person created.");
email = new ArrayList<Email>();
voice = new ArrayList<Voice>();
addresses = new ArrayList<Address>();
notes = new ArrayList<EntityNote>();
history = new ArrayList<EntityEvent>();
}
...
以下是我的电子邮件类的更完整的版本:
@Embeddable
@XmlAccessorType(XmlAccessType.FIELD)
public class Email implements Serializable {
final static Logger logger = LoggerFactory.getLogger(Email.class.getName());
static final long serialVersionUID = 1L;
@NotNull (message = "Email Type may not be null")
@Enumerated(EnumType.STRING)
private EmailType type;
@NotNull (message = "Email Address may not be null")
@Pattern(regexp = "[-0-9a-zA-Z.+_][email protected][-0-9a-zA-Z.+_]+.[a-zA-Z]{2,4}", message = "Email Address must match pattern [-0-9a-zA-Z.+_][email protected][-0-9a-zA-Z.+_]+.[a-zA-Z]{2,4}")
private String address;
private String description;
...
有趣:
我呼吁坚持在我的新的人,如下图所示工作过周围的bug通过手动进行验证。 JSF使用validateProperty部分验证Person实体,而validateProperty不尊重Person的email属性中的@Valid注释。这解释了为什么我的JSF客户端不报告约束违规。但是,我仍然不明白为什么当我坚持实体时,JPA级别没有验证电子邮件属性。我读过的所有内容都表明,默认情况下启用了bean验证。我是否必须将一些属性添加到我的persistence.xml文件以启用JPA级别bean验证?感谢您的帮助! – 2014-09-01 22:09:10
默认情况下启用JPA生命周期事件的验证,但也可以通过某些属性进行控制。参见http://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#d0e5193。为什么它不适用于你很难说,尤其是因为在你的例子中你没有显示你的JPA注释/配置。我建议打开调试级别日志记录来查看是否发生验证。如果您需要更多反馈,则需要更新您的问题并提供更多信息。 – Hardy 2014-09-02 09:31:27
我将一个org.hibernate.validator记录器添加到了我的GlassFish 4服务器配置中,并观察验证器验证firstName属性是否为空并与该模式匹配的位置。如果我将@Size(min = 1)注释添加到电子邮件属性中,我会发现验证程序验证电子邮件属性上列表的大小,但不验证组成该列表的电子邮件对象的地址属性。我用一些配置信息更新了我的原始问题。 – 2014-09-03 04:10:07