无法使用复合@IdClass映射实体

时间:2014-08-11 14:35:17

标签: java hibernate jpa

我有以下型号(更大型号的非常简化版本)

public enum EntityType {
    DOG, HAMMER
}

@Entity
public class Entity {
    @EmbeddedId
    private EntityKey key;
    private String someProp;
}

@Embeddable
public class EntityKey implements Serializable{
    private Long serial;
    @Enumerated(EnumType.STRING)
    private EntityType type;
}

@Entity
@IdClass(MetricKey.class)
public class Metric {
    @Id
    private EntityKey entityKey;
    @Id
    private Long timestamp;
    private Double sampledValue;
}

public class MetricKey implements Serializable {
    private EntityKey entityKey;
    private Long timestamp;
}

实体中的实体是一个大型层次结构根的抽象类。度量标准表示在特定时间点在实体上采样的一些数据。实体具有由类型和序列号组成的组合密钥,度量标准应具有由实体密钥+时间戳组成的组合密钥。

上面的代码从hibernate获取了这个异常:

org.hibernate.HibernateException: Unable to instantiate default tuplizer [org.hibernate.tuple.component.PojoComponentTuplizer]
    ...
Caused by: java.lang.reflect.InvocationTargetException
    ...
Caused by: org.hibernate.PropertyNotFoundException: field [serial] not found on Metric
    at org.hibernate.property.DirectPropertyAccessor.getField(DirectPropertyAccessor.java:166)
    ... 45 more

它似乎发现了EntityKey上的@Embeddable,并试图将其分开。

我知道我可以通过制作MetricKey @Embeddable并重写一些代码来解决这个问题:

@Entity
public class Metric {
    @EmbeddedId
    private MetricKey key;
    private Double sampledValue;
}
@Embeddable
public class MetricKey implements Serializable{
    private EntityKey entityKey;
    private Long timeStamp;
}

但我更喜欢原始设计,因为EntityKey在整个系统中被广泛使用,并且必须在EntityKeyMetricKey之间来回转换会让开发人员烦恼。

我做错了什么?

1 个答案:

答案 0 :(得分:0)

我可以建议您的唯一可行解决方案是将Metric的实现更改为

@Entity
@IdClass(MetricKey.class)
public class Metric {
    @Id
    @ManyToOne
    private Entity entity;
    @Id
    private Long timestamp;
    private Double sampledValue;
}

您还可以参考JPA 2.1规范的 2.4.1.1派生身份规范

  

如果实体中的Id属性是与父级的多对一或一对一关系   实体,id类中的相应属性必须与Java类型相同   父类实体的id类或嵌入式id(如果父实体具有复合主体)   key)或父实体的Id属性的类型(如果父实体具有   简单的主键)。

我的解决方案针对Hibernate 4.3.6进行了测试