как полностью отключить исключения Hibernate в Spring Boot - PullRequest
0 голосов
/ 26 мая 2018

У меня есть ситуация.Я создаю проект Spring Boot для взаимодействия с несколькими устаревшими объектами OpenJPA.

Проблема заключается в том, что, поскольку Spring Boot Starter Data JPA использует Hibernate в качестве базы, приложение Spring генерирует исключения Hibernate, такие как:

org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]
: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: 
Using default @DiscriminatorValue for a discriminator of type CHAR is not safe

Теперь, , хотя это легко исправить путем обновления кода сущности, мы не можем коснуться или изменить этот код .Мы должны оставить все как есть - не в соответствии со стандартами Hibernate.

Итак, есть ли 1010 * любой способ в Spring отключить подобные исключения Hibernate, чтобы мы могли принимать сущности, которые нене соответствует стандартам Hibernate и генерирует исключения Hibernate?

Наш дизайн кода прост, это стандартная настройка Service-Repository.Например:

PersonRepository.java:

public interface PersonRepository extends CrudRepository<Person, Long> {

    Person findFirstByPersonSsnSsn(String ssn);

    Person findFirstByPersonId(Integer personId);

}

PersonDomainService.java:

public interface PersonDomainService {

    Person findPersonBySsn(String ssn); 

    public Person findPerson(Integer id);
}

PersonDomainServiceImpl.java:

@Service
@Transactional
public class PersonDomainServiceImpl implements PersonDomainService {

    private PersonRepository personRepository;

    @Autowired
    public PersonDomainServiceImpl(PersonRepository personRepository) {
        this.personRepository = personRepository;
    }

    @Transactional(readOnly=true)
    public Person findPersonBySsn(String ssn) {
        Person person = personRepository.findFirstByPersonSsnSsn(ssn);

        System.out.println(person.getAddresses().size());
        System.out.println(person.getPhones().size());

        return person;

    }

    @Transactional(readOnly=true)
    public Person findPerson(Integer id) {
        // TODO Auto-generated method stub
        Person person = personRepository.findFirstByPersonId(id);

        System.out.println(person.getAddresses().size());
        System.out.println(person.getPhones().size());

        return person;
    }   
}

ИСущности довольно стандартные:

@Entity
@Table(name = "PERSON", schema = "SCHEMA")
public class Person implements Serializable, EntityWithAuditInfo {
...

1 Ответ

0 голосов
/ 26 мая 2018

Исключение указывает, что hibernate отказывается инициализировать себя, так что это не проблема обработки исключений, но вам нужно каким-то образом убедить hibernate для инициализации, даже если он чувствует, что дискриминатор "опасен".

Поиск по исходному коду hibernate показывает, что это исключение выброшено в

public void bindDiscriminatorValue() {
    if ( StringHelper.isEmpty( discriminatorValue ) ) {
        Value discriminator = persistentClass.getDiscriminator();
        if ( discriminator == null ) {
            persistentClass.setDiscriminatorValue( name );
        }
        else if ( "character".equals( discriminator.getType().getName() ) ) {
            throw new AnnotationException(
                    "Using default @DiscriminatorValue for a discriminator of type CHAR is not safe"
            );
        }
        else if ( "integer".equals( discriminator.getType().getName() ) ) {
            persistentClass.setDiscriminatorValue( String.valueOf( name.hashCode() ) );
        }
        else {
            persistentClass.setDiscriminatorValue( name ); //Spec compliant
        }
    }
    else {
        //persistentClass.getDiscriminator()
        persistentClass.setDiscriminatorValue( discriminatorValue );
    }
}

Как вы можете видеть, hibernate всегда будет выдавать такое исключение, если длядискриминатор типа char.Нет способа предотвратить изменение исходного кода для режима гибернации.

Этот метод вызывается из :

public void bindEntity() {
    persistentClass.setAbstract( annotatedClass.isAbstract() );
    persistentClass.setClassName( annotatedClass.getName() );
    persistentClass.setJpaEntityName(name);
    //persistentClass.setDynamic(false); //no longer needed with the Entity name refactoring?
    persistentClass.setEntityName( annotatedClass.getName() );
    bindDiscriminatorValue();

    persistentClass.setLazy( lazy );
    if ( proxyClass != null ) {
        persistentClass.setProxyInterfaceName( proxyClass.getName() );
    }
    persistentClass.setDynamicInsert( dynamicInsert );
    persistentClass.setDynamicUpdate( dynamicUpdate );

    ... and 170 more lines of code to parse all other annotations in this class
}

Как видно из отсутствия блока перехвата, hibernate прерывает синтаксический анализ этой сущности, если значение дискриминатора не можетбыть определенным.

Следовательно, даже самая последняя версия hibernate не может использоваться с сущностью, в которой отсутствует значение дискриминатора, когда дискриминатор имеет тип char.(Между прочим, существует открытый вопрос об этом , который не решался командой Hibernate в течение последних 7 лет)

Единственный способ решить эту проблему - это изменить сущность,изменение режима гибернации или использование другой реализации JPA.

...