2013-02-20 24 views
9

Câu hỏi này là theo dõi điều này: JPA ConstraintViolation vs RollbackHibernate không tuân thủ các thông số kỹ thuật JPA khi kết hợp với API xác nhận đậu?

Tôi đã thực hiện một số kiểm tra về sự kết hợp giữa JPA và API xác thực (JSR-303).

Tôi tìm thấy sau trong JPA specifications (trang 101-102):

Theo mặc định, mặc định Bean Validation nhóm (nhóm mặc định) sẽ được xác nhận khi tiền tồn tại và trước bản cập nhật xác nhận vòng đời sự kiện

...

Nếu bộ ConstraintViolation đối tượng được trả về bởi phương thức validate không phải là trống rỗng, các nhà cung cấp kiên trì phải ném javax.validation.ConstraintViolationException chứa một tham chiếu đến các thiết lập trở lại của ConstraintV đối tượng iolation, và phải đánh dấu giao dịch cho rollback.

tôi thiết lập các thử nghiệm sau đây:

  • HibernateValidator như JSR-303 thực hiện
  • 2 PersistenceProvider Hibernate và EclipseLink
  • một thực thể NameNotNullWithDefaultGeneratedStrategy với một id được tạo ra với chiến lược mặc định (@Generated) và @NotNull String name cột
  • pháp nhân khác NameNotNullWithTableGeneratedStrategy với id được tạo bằng chiến lược bảng (@TableGenerated) và @NotNull String name cột
  • thử nghiệm để thử persist một phiên bản của mỗi thực thể có giá trị name không.
  • kết quả mong đợi là javax.validation.ConstraintViolationException được ném theo phương pháp tồn tại và giao dịch được đánh dấu là rollback only (tức là các giả định đó dựa trên đặc điểm kỹ thuật JPA được trích dẫn trong bài đăng này).

Kết quả là:

  • với liên kết thực như một nhà cung cấp:
    • phương pháp persist ném một javax.validation.ConstraintViolationException cho cả các thực thể.
    • giao dịch được đánh dấu là rollback only trong cả hai trường hợp
  • với ngủ đông như một nhà cung cấp:
    • persist ném một javax.validation.ConstraintViolationException cho thực thể NameNotNullWithDefaultGeneratedStrategy + giao dịch đánh dấu là rollback only
    • persist không ném bất kỳ ngoại lệ đối với pháp nhân NameNotNullWithTableGeneratedStrategy + giao dịch không bị gắn cờrollback only
    • commit cho NameNotNullWithTableGeneratedStrategy không thành công với một RollbackException

Các câu hỏi là:

  • là nó thực sự là một sự vi phạm của chi tiết kỹ thuật JPA? hoặc tôi thiếu một cái gì đó với trường hợp cụ thể của chiến lược tạo bảng?
  • trong trường hợp vi phạm: có báo cáo lỗi nào liên quan đến báo cáo này không?

Đây là mã cho thử nghiệm của tôi:

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(); 
     } 
    } 
} 

Đối tượng

Mặc định chiến lược

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() {} 
} 

Bảng 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() {} 
} 

Các 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> 

Các 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

gì xảy ra với @column (nullable = false) cùng với @NotNull? –

+0

Tôi đã thử với '@Column (nullable = false)': cùng một kết quả – ben75

+1

Tôi thực sự không hiểu tại sao chiến lược tạo ảnh hưởng đến xác thực trong trường hợp này, tuy nhiên tôi chắc chắn sẽ mở một báo cáo lỗi như bạn đã thiết lập một testcase tái tạo , sau khi tước đi phần eclipselink) chống lại trình duyệt tính hợp lệ. –

Trả lời

Các vấn đề liên quan