Hibernate не соответствует спецификациям JPA в сочетании с API Bean Validation?

Этот вопрос является продолжением этого: JPA ConstraintViolation vs Rollback

Я провел некоторый тест на предмет сочетания JPA и API проверки (JSR-303).

Я нашел следующее в спецификациях JPA (стр. 101-102):

По умолчанию группа проверки компонентов по умолчанию (группа По умолчанию) будет проверяться после события предварительной проверки жизненного цикла до и после обновления

...

Если набор объектов ConstraintViolation, возвращаемых методом validate, не является пустым, поставщик сохраняемости должен выдать исключение javax.validation.ConstraintViolationException, содержащее ссылку на возвращенный набор объектов ConstraintViolation, и должен пометить транзакцию для отката.

Я настроил следующий тест:

  • HibernateValidator как реализация JSR-303
  • 2 PersistenceProvider Hibernate и EclipseLink
  • одна сущность NameNotNullWithDefaultGeneratedStrategy с идентификатор, сгенерированный с помощью стратегии по умолчанию (@Generated) и столбца @NotNull String name
  • , другой объект NameNotNullWithTableGeneratedStrategy с идентификатором, сгенерированным с помощью стратегии таблицы (@TableGenerated) и столбца @NotNull String name
  • тест попытаться persist один экземпляр каждого объекта с нулевым name.
  • Ожидаемые результаты - это javax.validation.ConstraintViolationException, генерируемый методом persist, и транзакция, помеченная как rollback only (т.е. эти предположения основаны на спецификации JPA, приведенной в этом посте).

Результаты:

  • с ссылкой на затмение в качестве поставщика:
    • метод persist выбрасывает javax.validation.ConstraintViolationException для обоих объектов.
    • транзакция помечается как rollback only в обоих случаях
  • с гибернацией в качестве поставщика:
    • persist выбрасывает javax.validation.ConstraintViolationException для сущности NameNotNullWithDefaultGeneratedStrategy ] + транзакция, помеченная как rollback only
    • persist, не выдает никаких исключений для сущности NameNotNullWithTableGeneratedStrategy + транзакция не помечена как rollback only
    • commit ] для NameNotNullWithTableGeneratedStrategy не удается с 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() {}
}

Таблица состояний:

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

    
    
        
            org.hibernate.ejb.HibernatePersistence
            com.example.jpa.validator.NameNotNullWithTableGeneratedStrategy
            com.example.jpa.validator.NameNotNullWithDefaultGeneratedStrategy
            
                
                
                
                
            
        
        
            org.eclipse.persistence.jpa.PersistenceProvider
            com.example.jpa.validator.NameNotNullWithTableGeneratedStrategy
            com.example.jpa.validator.NameNotNullWithDefaultGeneratedStrategy
            
                
                
                
                
            
        
    

Pom.xml

    
    
        4.0.0

        com.example
        com.example.jpa.validator
        1.0-SNAPSHOT
        
            4.2.0.CR1
            4.3.1.Final
            4.11
            1.3.170
        

        
            
                org.hibernate
                hibernate-validator
                ${hibernate-validator.version}
            
            
                com.h2database
                h2
                ${h2.version}
                test
            
            
                junit
                junit
                test
                ${junit.version}
            

            
                org.hibernate
                hibernate-core
                ${hibernate.version}
            
            
                org.hibernate
                hibernate-entitymanager
                ${hibernate.version}
            

            
                org.eclipse.persistence
                org.eclipse.persistence.jpa
                2.4.0
            
            
                org.eclipse.persistence
                javax.persistence
                2.0.0
            
        

        
            
                http://download.eclipse.org/rt/eclipselink/maven.repo/
                eclipselink
                default
                Repository for library EclipseLink (JPA 2.0)
            
        
    

10
задан Community 23 May 2017 в 11:53
поделиться