有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Hibernate仅在类为final时工作[否则将抛出SingleTableEntityPersister]

我曾尝试使用Hibernate 5.4.1构建非常简单的实体并将其保存在数据库中。最终版本和Java8。为了消除状态突变,跳过“setter”,并使用@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

我发现在制作产品类最终版后,一切正常。问题是,我不明白为什么你能帮我了解发生了什么事吗

一点代码。 这不起作用:

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 {

它是有效的

应用程序上下文。存储库。xml仅通知spring存储库的位置

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

在调试时,我还发现下面的一个异常是

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

你知道为什么需要“最终”吗

//编辑

安德洛尼卡指出了正确的方向:

现在我知道,若类不是final,hibernate会尝试构建一个代理,而异常来自 ByteBuddyProxyHelper。阶级

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) 个答案

  1. # 1 楼答案

    因此,几天的调试让我想到:

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

    古典喷射器。使用查找。isAvailable()-在Java8上抛出被Hibernate吞没的NoMethodError

  2. # 2 楼答案

    不确定,为什么使用final关键字它可以工作,也许它与代理生成有关。这里的问题是@Builder来自龙目岛,我想。有一个bug报告说,添加@Builder注释将删除hibernate所需的默认构造函数