Java 如何使用 JPA 验证模型数据?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21874393/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 11:12:26  来源:igfitidea点击:

How to validate model data with JPA?

javavalidationjpaeclipselink

提问by svenhuebner

I am trying to get JPA validation to work, however it seems that the validation annotations are ignored. I found this example of JPA validation on SO: JPA Entity Validation, but it does not work for me. The @NotNulland @Sizeannotations seem to be ignored.

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

As in the answer mentioned above I use only two classes:

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

Customer.java:

客户.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:

客户测试.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:

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:

<?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>

The test fails at the fail(...)so the exception is never thrown.

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

How can I make (any) validation work with JPA? I cannot use Hibernate or Spring.

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

Thank you for your help

感谢您的帮助

EDIT: added hibernate-validator to pom.xml (with no effect)

编辑:将 hibernate-validator 添加到 pom.xml (无效)

采纳答案by Koitoer

Add this to your pom.xmls.

将此添加到您的 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>

And set validation property to AUTO this must to be enable in persistence.xml

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

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

Or do it progrmatically.

或者以编程方式进行。

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

回答by wds

Do you have a runtime implementation of the validator on your classpath? Typically people seem to use hibernate validator. (e.g. indeed by adding hibernate-validator to your pom.xml)

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

edit: Your version of EclipseLink also looks quite old, it should be a JPA2 implementation. If it is a JPA1 implementation, you should register your own event listener, which will be a bit more work. You can find some hints in the eclipse docs(scroll down to JPA section), but it looks like you'll have to slightly edit the standard validators to make it work. This blogmight be helpful.

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