【问题标题】:How to validate model data with JPA?如何使用 JPA 验证模型数据?
【发布时间】:2014-03-19 10:10:12
【问题描述】:

我正在尝试让 JPA 验证正常工作,但似乎忽略了验证注释。我在 SO:JPA Entity Validation 上找到了这个 JPA 验证示例,但它对我不起作用。 @NotNull@Size 注释似乎被忽略了。

正如上面提到的答案,我只使用了两个类:

客户.java:

package com.validation.test;

import javax.persistence.*;
import javax.validation.constraints.*;

@Entity
@Table(name = "T_CUSTOMER")
public class Customer {
    @Id
    @NotNull
    @SequenceGenerator(name = "customerIdSeq", sequenceName = "T_CUSTOMER_ID_SEQ", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "customerIdSeq")
    private Long id;

    @NotNull
    @Size(min = 3, max = 80)
    private String name;

    public Customer() {};

    public Customer(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

CustomerTest.java:

package com.validation.test.test;

import static org.junit.Assert.*;

import javax.persistence.*;
import javax.validation.*;
import javax.validation.constraints.Size;

import org.junit.*;

import com.validation.test.Customer;

public class CustomerTest {
    private static EntityManagerFactory emf;
    private EntityManager em;

    @BeforeClass
    public static void createEntityManagerFactory() {
        emf = Persistence.createEntityManagerFactory("testPU");
    }

    @AfterClass
    public static void closeEntityManagerFactory() {
        emf.close();
    }

    @Before
    public void beginTransaction() {
        em = emf.createEntityManager();
        em.getTransaction().begin();
    }

    @After
    public void rollbackTransaction() {
        if (em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }
        if (em.isOpen()) {
            em.close();
        }
    }

    @Test
    public void nameTooShort() {
        try {
            Customer customer = new Customer("bo");
            em.persist(customer);
            em.flush();
            fail("Expected ConstraintViolationException wasn't thrown.");
        } catch (ConstraintViolationException e) {
            assertEquals(1, e.getConstraintViolations().size());
            ConstraintViolation<?> violation = e.getConstraintViolations().iterator().next();

            assertEquals("name", violation.getPropertyPath().toString());
            assertEquals(Size.class, violation.getConstraintDescriptor().getAnnotation().annotationType());
        }
    }
}

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.validation.test</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>    
    <repositories>
        <repository>
            <id>maven2-repository.java.net</id>
            <name>Java.net Repository for Maven</name>
            <url>http://download.java.net/maven/2/</url>
            <layout>default</layout>
        </repository>    
    </repositories>    
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>javax.persistence</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>eclipselink</artifactId>
            <version>1.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.oracle</groupId>
                <artifactId>ojdbc5</artifactId>
            <version>11.2.0.2.0</version>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.0.0.GA</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.0.3.Final</version>
            <scope>test</scope>
        </dependency>
    </dependencies>    
    <build>
        <finalName>wwd-bs</finalName>
        <pluginManagement>
            <plugins>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.1</version>
                    <configuration>
                        <source>1.6</source>
                        <target>1.6</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.16</version>
                </plugin>    
            </plugins>
        </pluginManagement>    
    </build>
</project>

persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
    xmlns="http://java.sun.com/xml/ns/persistence">
    <persistence-unit name="testPU" transaction-type="RESOURCE_LOCAL">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <class>com.validation.test.Customer</class>
        <properties>
            <property name="eclipselink.logging.level" value="FINE" />
            <property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:orcl" />
            <property name="javax.persistence.jdbc.user" value="user" />
            <property name="javax.persistence.jdbc.password" value="password" />
            <property name="eclipselink.logging.level" value="INFO" />
        </properties>
    </persistence-unit>
</persistence>

测试在fail(...) 失败,因此永远不会抛出异常。

如何使用 JPA 进行(任何)验证?我不能使用 Hibernate 或 Spring。

感谢您的帮助

编辑:在 pom.xml 中添加了 hibernate-validator(无效)

【问题讨论】:

  • 您只包含了验证 API,但没有实现。检查@wds'链接并将带有 的部分复制到您的 pom.xml
  • 请参阅@wds 回答的第一条评论
  • 我看到了,但似乎没有,你做了我所说的(你的 pom.xml 显示)......
  • 我将 pom.xml 更改作为 EDIT 添加到问题中。

标签: java validation jpa eclipselink


【解决方案1】:

将此添加到您的 pom.xmls 中。

     <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>4.2.0.Final</version>
        <exclusions>
            <exclusion>
                <groupId>javax.xml.bind</groupId>
                <artifactId>jaxb-api</artifactId>
            </exclusion>
            <exclusion>
                <groupId>com.sun.xml.bind</groupId>
                <artifactId>jaxb-impl</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>1.0.0.GA</version>
    </dependency>

并将验证属性设置为 AUTO,这必须在 persistence.xml 中启用

<property name="javax.persistence.validation.mode" value="AUTO" />

或者以编程方式进行。

final Set<ConstraintViolation<Object>> errors = validator.validate(object, classes);

【讨论】:

  • 这行得通。非常感谢。我不必将验证属性设置为 AUTO。
  • 附录:我还必须按照@wds 的建议更新 eclipselink 版本(现在使用 2.5.0)。在 1.2.0 版中,每当验证某些内容时,我都会收到 ValidationException HV000041。
  • hibernate validator 使用自动模式时要小心:“AUTO: if Bean Validation is present in the classpath”。当在类路径上找不到验证器时,最好将其设置为 CALLBACK 以获取错误。
  • 使用 maven 进行测试,CALLBACK 让我可以找到我忘记在 EL 实现中添加测试依赖的所有地方,谢谢@secure_paul
【解决方案2】:

您的类路径上是否有验证器的运行时实现?通常人们似乎使用hibernate validator。 (例如,确实通过将 hibernate-validator 添加到您的 pom.xml)

edit:您的 EclipseLink 版本看起来也很旧,它应该是 JPA2 实现。如果是 JPA1 实现,你应该注册自己的事件监听器,这将是一个多一点的工作。您可以在eclipse docs(向下滚动到 JPA 部分)中找到一些提示,但看起来您必须稍微编辑标准验证器才能使其工作。 This blog 可能会有所帮助。

【讨论】:

  • 如果你的意思是在我的 pom.xml 中依赖 hibernate-validator,我已经尝试过了,但没有任何效果。如果这不是你的意思,你能说得更具体一点吗?我是整个 JavaEE/JPA/maven 环境的新手。
  • @svenhuebner 这确实是我的意思。我在上面提出了其他一些可能的罪魁祸首。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多