我有以下型号(更大型号的非常简化版本)
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
在整个系统中被广泛使用,并且必须在EntityKey
和MetricKey
之间来回转换会让开发人员烦恼。
我做错了什么?
答案 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进行了测试