【问题标题】:JPA entity without id没有 id 的 JPA 实体
【发布时间】:2011-04-18 18:23:03
【问题描述】:

我有一个结构如下的数据库:

CREATE TABLE entity (
    id SERIAL,
    name VARCHAR(255),
    PRIMARY KEY (id)
);

CREATE TABLE entity_property (
    entity_id SERIAL,
    name VARCHAR(255),
    value TEXT
);

当我尝试创建 EntityProperty 类时

@Entity
@Table(name="entity_property")
public class EntityProperty {

    private String name;
    private String value;

    @Column(name="name")
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    @Column(name="value", nullable=true, length=255)
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
}

我得到以下异常:

org.hibernate.AnnotationException: No identifier specified for entity: package.EntityProperty

我知道 JPA 实体必须有一个主键,但由于我无法控制的原因,我无法更改数据库架构。是否可以创建将与这样的数据库模式一起使用的 JPA (Hibernate) 实体?

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

    我猜你的entity_property 有一个复合键(entity_id, name),其中entity_identity 的外键。如果是这样,您可以将其映射如下:

    @Embeddable
    public class EntityPropertyPK {
        @Column(name = "name")
        private String name;
    
        @ManyToOne
        @JoinColumn(name = "entity_id")
        private Entity entity;
    
        ...
    }
    
    @Entity 
    @Table(name="entity_property") 
    public class EntityProperty { 
        @EmbeddedId
        private EntityPropertyPK id;
    
        @Column(name = "value")
        private String value; 
    
        ...
    }
    

    【讨论】:

    • 谢谢。但是在这种情况下如何直接访问实体“名称”属性?我的 JP-QL 查询只有在通过“entity.id.name”访问“name”时才能正常工作,但我认为这是不对的。
    • @mikhail:如果您不喜欢使用@EmbeddedId 的方法,您可以尝试使用@IdClass 的替代方法:docs.jboss.org/hibernate/stable/annotations/reference/en/…
    • EntityPropertyPK 的注释应该是@Embeddedable 而不是@Embedded
    • 是的,EntityPropertyPK 的注释必须是 @Embeddable,因为 @Embedded 只能应用于字段和方法。此外,EntityPropertyPK 类必须声明为Serializable
    • @mikhail : 你能告诉我你在 entity.java 文件中的映射吗
    【解决方案2】:

    我知道 JPA 实体必须有主键,但由于我无法控制的原因,我无法更改数据库结构。

    更准确地说,JPA 实体必须定义一些Id。但是 JPA Id 不一定必须映射到表的主键上(并且 JPA 可以以某种方式处理没有主键或唯一约束的表)。

    是否可以创建将与这样的数据库结构一起使用的 JPA (Hibernate) 实体?

    如果您在表中有一列或一组列具有唯一值,则可以在 JPA 中将此唯一列集用作您的 Id

    如果您的表根本没有唯一列,您可以将所有列用作Id

    如果您的表有一些 id 但您的实体没有,请将其设为Embeddable

    【讨论】:

    • 拜托,我是新人。如何通过这个小示例将所有列用作实体中的 ID:int SIN、int age、String name、String adresse。谢谢
    • "您可以使用所有列作为 Id",但我的表需要能够将相同的行存储为单独的记录;c
    【解决方案3】:

    请参阅Java 持久性一书:Identity and Sequencing

    您问题的相关部分是No Primary Key section

    有时您的对象或表没有主键。最佳解决方案 在这种情况下,通常是向对象添加生成的 id 和 桌子。如果您没有此选项,有时会有一列或 表中构成唯一值的一组列。您可以使用 这组独特的列作为您在 JPA 中的 id。 JPAId 不必总是匹配数据库表的主键 约束,也不需要主键或唯一约束。

    如果您的表确实没有唯一列,则使用所有列 作为身份证。通常,当这种情况发生时,数据是只读的,所以即使 如果表允许具有相同值的重复行,则对象 无论如何都会是一样的,所以 JPA 认为他们无关紧要 是同一个对象。允许更新和删除的问题是 没有办法唯一标识对象的行,所以所有 匹配的行将被更新或删除。

    如果您的对象没有 id,但它的表有,这很好。 使对象成为Embeddable 对象,可嵌入对象 没有身份证。您将需要一个Entity,其中包含 这个Embeddable 持久化和查询它。

    【讨论】:

      【解决方案4】:

      我猜你可以使用@CollectionOfElements(用于hibernate/jpa 1)/@ElementCollection(jpa 2)将“实体属性”的集合映射到Listentity中的List

      您可以创建EntityProperty 类型并使用@Embeddable 对其进行注释

      【讨论】:

      【解决方案5】:

      如果 entity 和 entity_property 之间存在一对一的映射,您可以使用 entity_id 作为标识符。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-08-03
        • 2013-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-11
        • 2014-02-19
        • 2015-05-10
        相关资源
        最近更新 更多