2013-02-20 5 views
9

この質問は次のとおりです。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
  • としてマークされています
    • persistrollback 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> 
+1

を)と@NotNull? –

+0

私は '@Column(nullable = false)'で試しました:同じ結果 – ben75

+1

世代戦略がこのケースで検証に影響を与える理由はわかりませんが、再現可能なテストケースを設定したので、間違いなくバグレポートを開きます、eclipselinkの部分を取り除いた後の)hibernate-validatorに対するものです。 –

答えて

関連する問題