Hibernate работает только тогда, когда класс является окончательным [в противном случае выбрасывается SingleTableEntityPersister] - PullRequest
0 голосов
/ 05 февраля 2019

Я попытался построить очень простую сущность и сохранить ее в БД, используя Hibernate 5.4.1.Final и Java8.Для устранения мутации состояния «сеттеры» пропускаются и вместо них используется @Access (AccessType.FIELD).К сожалению, когда загружается Hibernate, выдается это исключение:

org.springframework.beans.factory.BeanCreationException:
    Error creating bean with name 'entityManagerFactory' defined in class path resource [application-context.repositories.xml]:
    Invocation of init method failed; 
nested exception is javax.persistence.PersistenceException: 
    [PersistenceUnit: default] Unable to build Hibernate SessionFactory; 
nested exception is org.hibernate.MappingException: 
    Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister

Я обнаружил, что после финальной работы класса Product все работает.Проблема в том, что я не понимаю, почему ??? Не могли бы вы помочь мне понять, что происходит?

Немного кода.Это не работает:

import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Builder;
import lombok.Getter;

@Entity
@Access(AccessType.FIELD)
@Table(name = "product")
public class Product {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  @Getter
  private String name;

  @Getter
  private String colour;

  protected Product() {
  }

  @Builder
  public Product(String name, String colour) {
    this.name = name;
    this.colour = colour;
  }
}

бит, достаточно добавить окончательный

public final class Product {

, и это работает.

application-context.repositories.xml только информирует веснугде репозитории

  <jpa:repositories base-package="a.b.c.repositories"/>

Во время отладки я также обнаружил, что одно из нижележащих исключений

HibernateException ->  Unable to instantiate default tuplizer [org.hibernate.tuple.entity.PojoEntityTuplizer]

Есть идеи, почему требуется "final"?

// edit

Андроник указал правильное направление:

Теперь я знаю, что если класс не является окончательным, hibernate пытается построить прокси, и исключение происходит из ByteBuddyProxyHelper.class

return byteBuddyState.loadProxy( persistentClass, new TypeCache.SimpleKey(key), byteBuddy -> byteBuddy
        .ignore( byteBuddyState.getProxyDefinitionHelpers().getGroovyGetMetaClassFilter() )
        .with( new NamingStrategy.SuffixingRandom( PROXY_NAMING_SUFFIX, new NamingStrategy.SuffixingRandom.BaseNameResolver.ForFixedValue( persistentClass.getName() ) ) )
        .subclass( interfaces.length == 1 ? persistentClass : Object.class, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING )
        .implement( (Type[]) interfaces )
        .method( byteBuddyState.getProxyDefinitionHelpers().getVirtualNotFinalizerFilter() )
                .intercept( byteBuddyState.getProxyDefinitionHelpers().getDelegateToInterceptorDispatcherMethodDelegation() )
        .method( byteBuddyState.getProxyDefinitionHelpers().getHibernateGeneratedMethodFilter() )
                .intercept( SuperMethodCall.INSTANCE )
        .defineField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME, ProxyConfiguration.Interceptor.class, Visibility.PRIVATE )
        .implement( ProxyConfiguration.class )
                .intercept( byteBuddyState.getProxyDefinitionHelpers().getInterceptorFieldAccessor() )
);

Ответы [ 2 ]

0 голосов
/ 06 февраля 2019

Итак, дни отладки привели меня к:

    public static ClassLoadingStrategy<ClassLoader> resolveClassLoadingStrategy(Class<?> originalClass) {
        // This is available only for JDK 9+
        if ( !ClassInjector.UsingLookup.isAvailable() ) {
            return new ClassLoadingStrategy.ForUnsafeInjection( originalClass.getProtectionDomain() );
        }

        Method privateLookupIn;
        try {
            privateLookupIn = MethodHandles.class.getMethod( "privateLookupIn", Class.class, MethodHandles.Lookup.class );
        }
        catch (Exception e) {
            throw new HibernateException( LOG.bytecodeEnhancementFailed( originalClass.getName() ), e );
        }

ClassInjector.UsingLookup.isAvailable () - на Java8 выдает NoMethodError, который проглатывается Hibernate

0 голосов
/ 05 февраля 2019

Не уверен, почему с ключевым словом final это работает, может быть, это как-то связано с генерацией прокси.Здесь проблема @Builder от ломбок, я думаю.Сообщалось, что ошибка связана с тем, что добавление аннотации @Builder удаляет конструктор по умолчанию, необходимый для hibernate.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...