简体   繁体   English

休眠异常:无法在以@IdClass注释的实体中找到属性…

[英]Hibernate Exception: Unable to find properties … in entity annotated with @IdClass

I have this composite key class: 我有这个复合键类:

@Embeddable
public class TaskEntityId implements Serializable {
    private static final long serialVersionUID = 1L;

    public String objectUuid;
    @Column(name="DOMAIN_OBJECT_UUID", nullable=false, length=36)
    public String getObjectUuid() { return objectUuid; }
    public void setObjectUuid(String uuid) { this.objectUuid = uuid; }

    public String taskName;
    @Column(name = "TASK_NAME", nullable=false, length=32)
    public String getTaskName() { return taskName; }
    public void setTaskName(String taskName) { this.taskName = taskName; }

    public Date createdTimestamp = new Date();
    @Column(name = "CREATED_TS", nullable=false, updatable=false)
    @Temporal(TemporalType.TIMESTAMP)
    public Date getCreatedTimestamp() { return createdTimestamp; }
    public void setCreatedTimestamp(Date createdTimestamp) { this.createdTimestamp = createdTimestamp; }

    @Override
    public boolean equals(Object o) {...}

    @Override
    public int hashCode() {...}

    @Override
    public String toString() {...}
}

Which is used in this entity class: 在此实体类中使用的是:

@Entity
@Table(name = "TASK")
@IdClass(TaskEntityId.class)
public class TaskEntity implements Serializable {

    @EmbeddedId
    TaskEntityId id;

    public TaskEntityId getId() { return id; }

    public void setId(TaskEntityId id) { this.id = id; }

...

I also added to this class some extra getters based on suggestions to other similar questions: 我还根据对其他类似问题的建议,向该类添加了一些额外的获取器:

public String getObjectUuid() { return id.getObjectUuid(); }
public String getTaskName() { return id.getTaskName(); }
public Date getCreatedTimestamp() { return id.getCreatedTimestamp(); }

Still, I get this exception: 仍然,我得到这个异常:

Error in custom provider, org.hibernate.AnnotationException: Unable to find properties (createdTimestamp, objectUuid, taskName) in entity annotated with @IdClass:c.m.d.p.TaskEntity

The solution is to remove the 解决方法是删除

@IdClass(TaskEntityId.class)

annotation from the TaskEntity class. TaskEntity类中的注释。 And I also needed an empty default constructor. 而且我还需要一个空的默认构造函数。

To map a composite key, you can use the EmbeddedId or the IdClass annotations. 要映射组合键,可以使用EmbeddedId或IdClass批注。 I know this question is not strictly about JPA but the rules defined by the specification also applies. 我知道这个问题不仅仅涉及JPA,但规范定义的规则也适用。 So here they are: 因此,它们是:

2.1.4 Primary Keys and Entity Identity 2.1.4主键和实体身份

... ...

A composite primary key must correspond to either a single persistent field or property or to a set of such fields or properties as described below. 复合主键必须对应于单个持久性字段或属性,或对应于如下所述的一组此类字段或属性。 A primary key class must be defined to represent a composite primary key. 必须定义一个主键类来表示一个复合主键。 Composite primary keys typically arise when mapping from legacy databases when the database key is comprised of several columns. 当数据库键由几列组成时,从主数据库进行映射时,通常会出现复合主键。 The EmbeddedId and IdClass annotations are used to denote composite primary keys. EmbeddedId和IdClass批注用于表示复合主键。 See sections 9.1.14 and 9.1.15. 参见9.1.14和9.1.15节。

... ...

The following rules apply for composite primary keys: 以下规则适用于复合主键:

The primary key class must be public and must have a public no-arg constructor. 主键类必须是公共的,并且必须具有公共的无参数构造函数。 If property-based access is used, the properties of the primary key class must be public or protected. 如果使用基于属性的访问,则主键类的属性必须是公共的或受保护的。 The primary key class must be serializable. 主键类必须可序列化。 The primary key class must define equals and hashCode methods. 主键类必须定义equals和hashCode方法。 The semantics of value equality for these methods must be consistent with the database equality for the database types to which the key is mapped. 这些方法的值相等的语义必须与键映射到的数据库类型的数据库相等一致。 A composite primary key must either be represented and mapped as an embeddable class (see Section 9.1.14, “EmbeddedId Annotation”) or must be represented and mapped to multiple fields or properties of the entity class (see Section 9.1.15, “IdClass Annotation”). 复合主键必须表示并映射为可嵌入类(请参见第9.1.14节“ EmbeddedId注释”),或者必须表示并映射至实体类的多个字段或属性(请参见第9.1.15节“ IdClass”)注解”)。 If the composite primary key class is mapped to multiple fields or properties of the entity class, the names of primary key fields or properties in the primary key class and those of the entity class must correspond and their types must be the same. 如果组合主键类映射到实体类的多个字段或属性,则主键类中的主键字段或属性名称与实体类的名称必须对应,并且它们的类型必须相同。

With an IdClass 有一个IdClass

The class for the composite primary key could look like (could be a static inner class): 复合主键的类可能看起来像(可以是静态内部类):

public class TimePK implements Serializable {
    protected Integer levelStation;
    protected Integer confPathID;

    public TimePK() {}

    public TimePK(Integer levelStation, String confPathID) {
        this.id = levelStation;
        this.name = confPathID;
    }
    // equals, hashCode
}

And the entity: 和实体:

@Entity
@IdClass(TimePK.class)
class Time implements Serializable {
    @Id
    private Integer levelStation;
    @Id
    private Integer confPathID;

    private String src;
    private String dst;
    private Integer distance;
    private Integer price;

    // getters, setters
}

The IdClass annotation maps multiple fields to the table PK. IdClass批注将多个字段映射到表PK。

With EmbeddedId 使用EmbeddedId

The class for the composite primary key could look like (could be a static inner class): 复合主键的类可能看起来像(可以是静态内部类):

* *

@Embeddable
public class TimePK implements Serializable {
    protected Integer levelStation;
    protected Integer confPathID;
    public TimePK() {}
    public TimePK(Integer levelStation, String confPathID) {
        this.id = levelStation;
        this.name = confPathID;
    }
    // equals, hashCode
}

* And the entity: *和实体:

@Entity
class Time implements Serializable {
    @EmbeddedId
    private TimePK timePK;

    private String src;
    private String dst;
    private Integer distance;
    private Integer price;

    //...
}

The @EmbeddedId annotation maps a PK class to table PK. @EmbeddedId批注将PK类映射到表PK。

Differences: 差异:

From the physical model point of view, there are no differences EmbeddedId somehow communicates more clearly that the key is a composite key and IMO makes sense when the combined pk is either a meaningful entity itself or it reused in your code. 从物理模型的角度来看,EmbeddedId在某种程度上可以更清楚地表明密钥是组合密钥,并且组合的pk本身是有意义的实体或可以在代码中重用时,IMO才有意义。 @IdClass is useful to specify that some combination of fields is unique but these do not have a special meaning. @IdClass可用于指定某些字段组合是唯一的,但这些字段没有特殊含义。 They also affect the way you write queries (making them more or less verbose): 它们还会影响您编写查询的方式(使它们或多或少变得冗长):

with IdClass 与IdClass

select t.levelStation from Time t 从时间t选择t.levelStation

with EmbeddedId 与EmbeddedId

select t.timePK.levelStation from Time t 从时间t中选择t.timePK.levelStation

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM