声明的元模型属性工作正常,但继承的元模型属性为 NULL。为啥?

Posted

技术标签:

【中文标题】声明的元模型属性工作正常,但继承的元模型属性为 NULL。为啥?【英文标题】:Declared metamodel attributes work fine BUT Inherited Metamodel Attributes are NULL. Why?声明的元模型属性工作正常,但继承的元模型属性为 NULL。为什么? 【发布时间】:2011-05-03 21:18:10 【问题描述】:

我无法运行以下测试:-

@Test
public void test() 
    EntityManager em = entityManagerFactory.createEntityManager();
    em.getTransaction().begin();

    CriteriaBuilder builder = em.getCriteriaBuilder();
    CriteriaQuery<Project> query = builder.createQuery(Project.class);

    Root<Project> project = query.from(Project.class);

    Path<String> name = project.get(Project_.name);
    Assert.assertNotNull(name);

    Path<EntityLifeCycleImpl> lifeCycle = project.get(Project_.lifeCycle); // problem is here, throws NullPointer
    Assert.assertNotNull(lifeCycle);

它在project.get(Project_.lifeCycle) 行抛出 NullPointerException。为什么?

java.lang.NullPointerException
    at org.hibernate.ejb.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:138)

PersistenceEntityBase.java

import org.hibernate.annotations.GenericGenerator;
        @MappedSuperclass
@Access(AccessType.PROPERTY)
public abstract class PersistentEntityBase 

protected String identifier;

protected EntityLifeCycleImpl lifeCycle = new EntityLifeCycleImpl();

protected PersistentEntityBase() 


@Id
@GeneratedValue(generator="generator") 
@GenericGenerator(name="generator", strategy="guid", parameters = )
@Column(name="identifier")
public String getIdentifier() 
    return identifier;


public void setIdentifier(String identifier) 
    this.identifier = identifier;


@Embedded
public EntityLifeCycleImpl getLifeCycle() 
    return lifeCycle;

public void setLifeCycle(EntityLifeCycleImpl lifeCycle) 
    this.lifeCycle = lifeCycle;

Project.java

@Entity
@Table(name="project")
@Access(AccessType.PROPERTY)
public class Project extends PersistentEntityBase 

    private String name;

    protected Project() 
    

    public Project(String name) 
        this();
        this.name = name;
    

    @Column(name="name", nullable=false, unique=true)
    public String getName() 
        return name;

public void setName(String name) 
    this.name = name;

EntityLifeCycleImpl.java

@Embeddable
public class EntityLifeCycleImpl implements EntityLifeCycle 
    private String createdBy;
    private Date createdDate;
       @Column(name="created_by")
public String getCreatedBy() 
    return createdBy;

public void setCreatedBy(String createdBy) 

    this.createdBy = createdBy;


@Column(name="created_date")
public Date getCreatedDate() 
    return createdDate;

public void setCreatedDate(Date createdDate) 
    this.createdDate = createdDate;

PersistentEntityBase_.java(使用 Hibernate 元模型生成器生成)

   @StaticMetamodel(PersistentEntityBase.class)
public abstract class PersistentEntityBase_ 
    public static volatile SingularAttribute<PersistentEntityBase, EntityLifeCycleImpl> lifeCycle;
        public static volatile SingularAttribute<PersistentEntityBase, String> identifier;
     

Project_.java

    @StaticMetamodel(Project.class)
public abstract class Project_ extends PersistentEntityBase_ 
    public static volatile SingularAttribute<Project, String> name;
    

EntityLifeCycleImpl_.java

   @StaticMetamodel(EntityLifeCycleImpl.class)
public abstract class EntityLifeCycleImpl_ 
    public static volatile SingularAttribute<EntityLifeCycleImpl, String> createdBy;
    public static volatile SingularAttribute<EntityLifeCycleImpl, Date> createdDate;

persistence.xml(仅相关部分)

<class>com.comp.timetracking.entity.PersistentEntityBase</class>
<class>com.comp.timetracking.entity.Project</class>

编辑: 我使用 hibernate-entitymanager.3.6.0.Final 和 hibernate-jpamodelgen.1.0.0.Final。

编辑 2 @帕斯卡 我认为 Hibernate EM 3.6.0.Final 允许我们在 @Entity 级别定义 @Embedded 注释字段,但它在 @MappedSuperclass 级别拒绝此类字段。你说什么?

由于我在此处看不到“文件上传选项”,因此我已在我的 esnips 帐户中上传了 TestCase。 Download 基于 maven 的项目并运行 SingularAttributeTest.java。并检查控制台输出

ERROR main metamodel.MetadataContext:413 - Unable to locate static metamodel field : timetracking.entity.Employee_#lifeCycle

点击“下载 embedded-singular-attribute.zip”链接下载文件,无需安装下载管理器。 (如果你点击Download link with Green arrow,你必须安装下载管理器!!)

【问题讨论】:

这个问题的副本:- forum.hibernate.org/viewtopic.php?f=1&t=1008173 【参考方案1】:

我使用 EclipseLink 测试了您的类和测试用例(我删除了 Hibernate 特定部分)并且测试通过了。但它确实在 Hibernate 3.5.6 中失败了。看起来像 Hibernate 中的一个错误。

顺便说一句,您的Embeddable 中缺少Temporal 注释

@Column(name = "created_date")
@Temporal(TemporalType.DATE)
public Date getCreatedDate() 
    return createdDate;

而且您不应该在persistence.xml 中声明PersistentEntityBase(映射的超类不是实体)。

【讨论】:

+1 你的意思是我应该使用 EclipseLink 而不是 Hibernate EM?感谢您提供有关 @Temporal 注释的信息。 @becomputer06:我实质上是在指出您的案例适用于 RI,并且该问题听起来像是 Hibernate 中的错误,您应该报告它(使用测试案例)。如果没有人报告,错误将无法修复。但我不能说这个问题是否严重到足以让你证明转移到另一个提供商是合理的(没有什么阻止 IMO,烦人的是,阻止不)。其他提供商也不是没有错误。你的电话:)【参考方案2】:

我遇到了同样的问题:在部署期间 jboss 7.0.2 报告了以下错误: “无法定位静态元模型字段 X” 其中 X 是继承自 @MappedSuperclass 并使用 @Embedded 注解的字段(X 的类型是使用 @Embeddable 注解的类)。

我解决了这个问题,将@Embeddable 和@MappedSuperclass 注释的类连同@Entity 注释的类一起添加到由持久性单元管理的类列表中。这是在“persistence.xml”文件中配置的。

【讨论】:

@Andro Selva 我在这里也面临同样的问题。即使@Embeddable 类在persistence.xml 文件中注册。【参考方案3】:

这不是问题。

来自 Hibernate 文档:

如果类 X 扩展了另一个类 S,其中 S 是由 X 扩展的最派生的托管类(即实体或映射超类),则类 X_ 必须扩展类 S_,其中 S_ 是为 S 创建的元模型类。

https://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/metamodel.html

【讨论】:

我应该自己想到的,就像一个魅力

以上是关于声明的元模型属性工作正常,但继承的元模型属性为 NULL。为啥?的主要内容,如果未能解决你的问题,请参考以下文章

子类 Django ModelBase(Django 模型的元类)

从 t4 脚手架模板访问我的模型中的元数据(数据注释)

Django:从带有元的抽象类的多重继承

MetadataException:无法加载指定的元数据资源

关系模型和关系运算理论

EEPlat的元模型体系