问题描述
这个问题跟随这个问题:
我对JPA和验证API(JSR-303)的组合进行了一些测试。
在(第101-102页):
lockquote
默认情况下,默认的Bean验证组(默认组)在预留持续时间和更新前的生命周期验证事件中进行验证。
...
由validate方法返回的ConstraintViolation对象不为空,则持久性提供程序必须抛出包含对返回的ConstraintViolation对象集的引用的javax.validation.ConstraintViolationException,并且必须标记tr
我设置了以下测试: 问题是: 以下是我测试的代码: 实体 默认策略
$ b 结果如下:
package com.example .jpa.validator;
import org.junit.Assert;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.RollbackException;
public class ConstraintViolationExceptionTest {
@Test
public void testHibernateDefaultStrategy(){//成功
testPersistWithNullName(pu-hibernate,new NameNotNullWithDefaultGeneratedStrategy( ));
}
@Test
public void testHibernateTableStrategy(){
testPersistWithNullName(pu-hibernate,new NameNotNullWithTableGeneratedStrategy());
//此测试失败:
//java.lang.AssertionError:期望javax.validation.ConstraintViolationException,但persist()成功!
$ b @Test
public void testEclipseLinkDefaultStrategy(){//成功
testPersistWithNullName(pu-eclipselink,new NameNotNullWithDefaultGeneratedStrategy());
$ b @Test
public void testEclipseLinkTableStrategy(){//成功
testPersistWithNullName(pu-eclipselink,new NameNotNullWithTableGeneratedStrategy());
}
private void testPersistWithNullName(String persistenceUnitName,Object entity){
EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName);
EntityManager entityManager = emf.createEntityManager();
try {
final EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
尝试{
尝试{
entityManager.persist(entity);
Assert.fail(期待javax.validation.ConstraintViolationException,但persist()成功!);
} catch(javax.validation.ConstraintViolationException cve){
//预计
Assert.assertTrue(根据JPA规范事务必须被标记为只回滚,transaction.getRollbackOnly()) ;
catch(Exception e){
Assert.assertTrue(根据JPA规范事务必须标记为只回滚,transaction.getRollbackOnly());
e.printStackTrace();
Assert.fail(期望得到一个javax.validation.ConstraintViolationException,但得到了+ e.getClass());
}
transaction.commit();
Assert.fail(持续使用null name !!!);
} catch(RollbackException e){
//这就是所期望的
} catch(Exception e){
e.printStackTrace();
Assert.fail(Unexpected exception:+ e.getMessage());
}
} finally {
entityManager.close();
$ b $
package com.example.jpa 。验证器;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;
@Entity
public class NameNotNullWithDefaultGeneratedStrategy {
@Id @GeneratedValue private Long id;
@NotNull public String name;
public NameNotNullWithDefaultGeneratedStrategy(){}
}
表状态:
package com.example.jpa.validator;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.TableGenerator;
import javax.validation.constraints.NotNull;
@Entity
public class NameNotNullWithTableGeneratedStrategy {
@GeneratedValue(strategy = GenerationType.TABLE,
generator =NAME_MUST_NOT_BE_NULL_ID_GENERATOR)
@ TableGenerator(name =NAME_MUST_NOT_BE_NULL_ID_GENERATOR)
@Id @NotNull私人长ID;
@NotNull public String name;
public NameNotNullWithTableGeneratedStrategy(){}
}
持久性。 xml
<?xml version =1.0encoding =UTF-8?>
< persistence version =2.0xmlns =http://java.sun.com/xml/ns/persistence
xmlns:xsi =http://www.w3.org/ 2001 / XMLSchema-instance
xsi:schemaLocation =http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd >
< persistence-unit name =pu-hibernatetransaction-type =RESOURCE_LOCAL>
< provider> org.hibernate.ejb.HibernatePersistence< / provider>
< class> com.example.jpa.validator.NameNotNullWithTableGeneratedStrategy< / class>
< class> com.example.jpa.validator.NameNotNullWithDefaultGeneratedStrategy< / class>
<属性>
< property name =javax.persistence.jdbc.drivervalue =org.h2.Driver/>
< property name =javax.persistence.jdbc.urlvalue =jdbc:h2:mem:test_mem_hibernate/>
< property name =hibernate.hbm2ddl.autovalue =create-drop/>
< property name =hibernate.dialectvalue =org.hibernate.dialect.H2Dialect/>
< / properties>
< / persistence-unit>
< persistence-unit name =pu-eclipselinktransaction-type =RESOURCE_LOCAL>
< provider> org.eclipse.persistence.jpa.PersistenceProvider< / provider>
< class> com.example.jpa.validator.NameNotNullWithTableGeneratedStrategy< / class>
< class> com.example.jpa.validator.NameNotNullWithDefaultGeneratedStrategy< / class>
<属性>
< property name =javax.persistence.jdbc.drivervalue =org.h2.Driver/>
< property name =javax.persistence.jdbc.urlvalue =jdbc:h2:mem:test_mem/>
< property name =eclipselink.ddl-generationvalue =create-tables/>
< property name =eclipselink.target-databasevalue =org.eclipse.persistence.platform.database.H2Platform/>
< / properties>
< / persistence-unit>
< /余辉>
pom.xml
<?xml version =1.0encoding =UTF-8?>
< 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.example< / groupId>
< artifactId> com.example.jpa.validator< / artifactId>
< version> 1.0-SNAPSHOT< / version>
<属性>
< hibernate.version> 4.2.0.CR1< /hibernate.version>
< hibernate-validator.version> 4.3.1.Final< /hibernate-validator.version>
< junit.version> 4.11< /junit.version>
< h2.version> 1.3.170< /h2.version>
< / properties>
<依赖关系>
< dependency>
< groupId> org.hibernate< / groupId>
< artifactId> hibernate-validator< / artifactId>
< version> $ {hibernate-validator.version}< / version>
< /依赖关系>
< dependency>
< groupId> com.h2database< / groupId>
< artifactId> h2< / artifactId>
< version> $ {h2.version}< / version>
< scope> test< / scope>
< /依赖关系>
< dependency>
< groupId> junit< / groupId>
< artifactId> junit< / artifactId>
< scope> test< / scope>
< version> $ {junit.version}< / version>
< /依赖关系>
< dependency>
< groupId> org.hibernate< / groupId>
< artifactId> hibernate-core< / artifactId>
< version> $ {hibernate.version}< / version>
< /依赖关系>
< dependency>
< groupId> org.hibernate< / groupId>
< artifactId> hibernate-entitymanager< / artifactId>
< version> $ {hibernate.version}< / version>
< /依赖关系>
< dependency>
< groupId> org.eclipse.persistence< / groupId>
< artifactId> org.eclipse.persistence.jpa< / artifactId>
< version> 2.4.0< / version>
< /依赖关系>
< dependency>
< groupId> org.eclipse.persistence< / groupId>
< artifactId> javax.persistence< / artifactId>
< version> 2.0.0< / version>
< /依赖关系>
< /依赖关系>
< repositories>
< repository>
< url> http://download.eclipse.org/rt/eclipselink/maven.repo/< / url>
< id> eclipselink< / id>
< layout>预设< / layout>
< name>库EclipseLink库(JPA 2.0)< / name>
< / repository>
< / repositories>
< / project>
=https://hibernate.onjira.com/browse/HHH-8028 =nofollow> https://hibernate.onjira.com/browse/HHH-8028
This question is a follow up to this one : JPA ConstraintViolation vs Rollback
I did some test about combination of JPA and validation API (JSR-303).
I found the following in JPA specifications (page 101-102):
I setup the following test:
- HibernateValidator as JSR-303 implementation
- 2 PersistenceProvider Hibernate and EclipseLink
- one entity NameNotNullWithDefaultGeneratedStrategy with an id generated with default strategy (@Generated) and @NotNull String name column
- another entity NameNotNullWithTableGeneratedStrategy with an id generated with table strategy (@TableGenerated) and @NotNull String name column
- the test try to persist one instance of each entity with a null name.
- the expected results are a javax.validation.ConstraintViolationException thrown by the persist method and the transaction marked as rollback only (i.e. those assumptions are based on JPA specification quoted in this post).
The results are :
- with eclipse link as a provider :
- the persist method throws a javax.validation.ConstraintViolationException for both entities.
- the transaction is marked as rollback only in both cases
- with hibernate as a provider :
- persist throws a javax.validation.ConstraintViolationException for entity NameNotNullWithDefaultGeneratedStrategy + transaction marked as rollback only
- persist don't throw any exception for entity NameNotNullWithTableGeneratedStrategy + transaction not flagged as rollback only
- commit for NameNotNullWithTableGeneratedStrategy fails with a RollbackException
The questions are :
- is it really a violation of JPA specifications ? or I am missing something with particular case of table generated strategy ?
- in case it is a violation: is there any existing bug report related to it ?
Here is the code for my test:
package com.example.jpa.validator; import org.junit.Assert; import org.junit.Test; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; import javax.persistence.RollbackException; public class ConstraintViolationExceptionTest { @Test public void testHibernateDefaultStrategy() { // Success testPersistWithNullName("pu-hibernate",new NameNotNullWithDefaultGeneratedStrategy()); } @Test public void testHibernateTableStrategy() { testPersistWithNullName("pu-hibernate",new NameNotNullWithTableGeneratedStrategy()); //this test fail with : //java.lang.AssertionError: Expecting a javax.validation.ConstraintViolationException, but persist() succeed ! } @Test public void testEclipseLinkDefaultStrategy() { // Success testPersistWithNullName("pu-eclipselink",new NameNotNullWithDefaultGeneratedStrategy()); } @Test public void testEclipseLinkTableStrategy() { // Success testPersistWithNullName("pu-eclipselink",new NameNotNullWithTableGeneratedStrategy()); } private void testPersistWithNullName(String persistenceUnitName, Object entity){ EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName); EntityManager entityManager = emf.createEntityManager(); try { final EntityTransaction transaction = entityManager.getTransaction(); transaction.begin(); try { try { entityManager.persist(entity); Assert.fail("Expecting a javax.validation.ConstraintViolationException, but persist() succeed !"); } catch (javax.validation.ConstraintViolationException cve) { //That's expected Assert.assertTrue("According JPA specs transaction must be flagged as rollback only",transaction.getRollbackOnly()); } catch (Exception e) { Assert.assertTrue("According JPA specs transaction must be flagged as rollback only",transaction.getRollbackOnly()); e.printStackTrace(); Assert.fail("Expecting a javax.validation.ConstraintViolationException, but got " + e.getClass()); } transaction.commit(); Assert.fail("persisted with null name !!!"); } catch (RollbackException e) { //That's expected } catch (Exception e) { e.printStackTrace(); Assert.fail("Unexpected exception :"+e.getMessage()); } } finally { entityManager.close(); } } }
The entities
Default strategy
package com.example.jpa.validator; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.validation.constraints.NotNull; @Entity public class NameNotNullWithDefaultGeneratedStrategy { @Id @GeneratedValue private Long id; @NotNull public String name; public NameNotNullWithDefaultGeneratedStrategy() {} }
Table stategy:
package com.example.jpa.validator; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.TableGenerator; import javax.validation.constraints.NotNull; @Entity public class NameNotNullWithTableGeneratedStrategy { @GeneratedValue(strategy = GenerationType.TABLE, generator = "NAME_MUST_NOT_BE_NULL_ID_GENERATOR") @TableGenerator(name = "NAME_MUST_NOT_BE_NULL_ID_GENERATOR") @Id @NotNull private Long id; @NotNull public String name; public NameNotNullWithTableGeneratedStrategy() {} }
The persistence.xml
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="pu-hibernate" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>com.example.jpa.validator.NameNotNullWithTableGeneratedStrategy</class> <class>com.example.jpa.validator.NameNotNullWithDefaultGeneratedStrategy</class> <properties> <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/> <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test_mem_hibernate"/> <property name="hibernate.hbm2ddl.auto" value="create-drop"/> <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/> </properties> </persistence-unit> <persistence-unit name="pu-eclipselink" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>com.example.jpa.validator.NameNotNullWithTableGeneratedStrategy</class> <class>com.example.jpa.validator.NameNotNullWithDefaultGeneratedStrategy</class> <properties> <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/> <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test_mem"/> <property name="eclipselink.ddl-generation" value="create-tables"/> <property name="eclipselink.target-database" value="org.eclipse.persistence.platform.database.H2Platform"/> </properties> </persistence-unit> </persistence>
The pom.xml
<?xml version="1.0" encoding="UTF-8"?> <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.example</groupId> <artifactId>com.example.jpa.validator</artifactId> <version>1.0-SNAPSHOT</version> <properties> <hibernate.version>4.2.0.CR1</hibernate.version> <hibernate-validator.version>4.3.1.Final</hibernate-validator.version> <junit.version>4.11</junit.version> <h2.version>1.3.170</h2.version> </properties> <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>${hibernate-validator.version}</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>${h2.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> <version>${junit.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.jpa</artifactId> <version>2.4.0</version> </dependency> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>javax.persistence</artifactId> <version>2.0.0</version> </dependency> </dependencies> <repositories> <repository> <url>http://download.eclipse.org/rt/eclipselink/maven.repo/</url> <id>eclipselink</id> <layout>default</layout> <name>Repository for library EclipseLink (JPA 2.0)</name> </repository> </repositories> </project>
I filed a bug report for this : https://hibernate.onjira.com/browse/HHH-8028
这篇关于与Bean验证API结合使用时,Hibernate不遵循JPA规范?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!