この質問は次のとおりです。JPA ConstraintViolation vs RollbackBean検証APIと組み合わせた場合、JPA仕様に従わないHibernate?
JPAと検証API(JSR-303)の組み合わせについていくつかのテストを行いました。
私はJPA specifications(ページ101-102)に、次のが見つかりました:デフォルトで
、デフォルトビーン検証・グループ(グループデフォルト)事前持続し、更新前のライフサイクルの検証時に検証されますイベント
...
ConstraintViolationのセットが空でない、持続性プロバイダがConstraintVの返されたセットへの参照を含むjavax.validation.ConstraintViolationExceptionをスローする必要がありvalidateメソッドによって返されたオブジェクト場合ロールバックのためにトランザクションをマークする必要があります。
Iセットアップ次のテスト:として
- HibernateValidator JSR-303実装
- 2はPersistenceProvider HibernateとEclipseLinkの
- つのデフォルト戦略(
@Generated
)と@NotNull String name
で生成されたIDを持つエンティティNameNotNullWithDefaultGeneratedStrategy
列 - 別のエンティティ
NameNotNullWithTableGeneratedStrategy
が、テーブル戦略(@TableGenerated
)と@NotNull String name
カラム - 試験は、
name
のヌルを持つ各エンティティの1つのインスタンスを試してみてください(persist
)。 - 予想される結果は、persistメソッドによってスローされた
javax.validation.ConstraintViolationException
であり、トランザクションはrollback only
とマークされています(これらの仮定はこの記事で引用されたJPA仕様に基づいています)。
結果は、次のとおりプロバイダとして日食リンクを
- :
persist
方法は、両方のエンティティのjavax.validation.ConstraintViolationException
をスロー。- 取引は、プロバイダとしてHibernateで両方のケースで
rollback only
- としてマークされています
persist
はrollback only
persist
としてマークされたエンティティNameNotNullWithDefaultGeneratedStrategy
+トランザクションのjavax.validation.ConstraintViolationException
は、いずれかをスローしないスローエンティティNameNotNullWithTableGeneratedStrategy
+トランザクションにはフラグが設定されていませんとしてrollback only
ため
commit
が質問があるRollbackException
で失敗します。
- それは本当にJPA仕様に違反しているのですか?またはテーブル生成戦略の特定のケースで何かが不足していますか?
- 違反の場合:既存のバグレポートはありますか?ここで
私のテストのためのコードです:
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() {}
}
表の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() {}
}
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>
を)と@NotNull? –
私は '@Column(nullable = false)'で試しました:同じ結果 – ben75
世代戦略がこのケースで検証に影響を与える理由はわかりませんが、再現可能なテストケースを設定したので、間違いなくバグレポートを開きます、eclipselinkの部分を取り除いた後の)hibernate-validatorに対するものです。 –