这个问题是该问题的后续解决方案:JPAConstraintViolation与回滚
我对JPA和验证API(JSR-303)的组合进行了一些测试。
我在JPA规范中找到了以下内容(第101-102页):
默认情况下,默认Bean验证组(默认组)将在持久化和更新前生命周期验证事件时进行验证 … 如果validate方法返回的ConstraintViolation对象集不为空,则持久性提供程序必须抛出javax.validation.ConstraintViolationException,其中包含对返回的ConstraintViolation对象集的引用,并且必须将事务标记为回滚。
默认情况下,默认Bean验证组(默认组)将在持久化和更新前生命周期验证事件时进行验证
…
如果validate方法返回的ConstraintViolation对象集不为空,则持久性提供程序必须抛出javax.validation.ConstraintViolationException,其中包含对返回的ConstraintViolation对象集的引用,并且必须将事务标记为回滚。
我设置以下测试:
NameNotNullWithDefaultGeneratedStrategy
@Generated
@NotNull String name
NameNotNullWithTableGeneratedStrategy
@TableGenerated
persist
name
javax.validation.ConstraintViolationException
rollback only
结果是:
commit
RollbackException
问题是:
这是我测试的代码:
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(); } } }
实体
默认策略
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() {} }
表策略:
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() {} }
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>
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>
我为此提交了一个错误报告:https : //hibernate.onjira.com/browse/HHH-8028