【问题标题】:JPA inheritance using SINGLE_TABLE - discriminator value doesn't match class使用 SINGLE_TABLE 的 JPA 继承 - 鉴别器值与类不匹配
【发布时间】:2012-06-15 12:25:50
【问题描述】:

使用单个表的 JPA 类层次结构有一个奇怪的行为。 基本上我有两个实体 EntityMapA 和 EntityMapB,它们都扩展了 EntityMap。鉴别器值为“ENTITY_TYPE”,EntityMapA 为 A,EntityMapB 为 B。 不知何故,我得到了 EntityMapA 类型的对象,其中鉴别器值设置为“B”!

我使用 Hibernate 3.3 作为 JPA 提供程序。

代码如下:

@Entity
@Table(name="ENTITY_MAP")
@DiscriminatorColumn(name = "ENTITY_TYPE")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class EntityMap implements Serializable {

    /**
     *
     */
    private static final long serialVersionUID = 1L;
    private Long entityMapId;

    //This is a ID of another entity we map to. It is a different entity type depending on 
    //The subclass. For EntityMapA it would map to EntityA and for EntityMapB it would map   
    // to EntityB
    private Long entityId;


    private String discriminator;

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "ENTITY_MAP_ID", unique = true, nullable = false)
    public Long getEntityMapId() {
        return entityMapId;
    }
    public void setEntityMapId(Long EntityMapId) {
        this.entityMapId = entityMapId;
    }


    @Column(name="ENTITY_TYPE",insertable=false,updatable=false)
    public String getDiscriminator() {
        return discriminator;
    }
    public void setDiscriminator(String discriminator) {
        this.discriminator = discriminator;
    }

    @Column(name="ENTITY_ID",insertable=false,updatable=false)
    public Long getEntityId() {
        return entityId;
    }
    public void setEntityId(Long entityId) {
        this.entityId = entityId;
    }

    //there are other common fields in here which are left out    
}


@Entity
@DiscriminatorValue("A")
public class EntityMapA extends EntityMap {

    /**
     *
     */
    private static final long serialVersionUID = -8709307036005000705L;

    private EntityA entityA;

    public static final String DISCRIMINATOR = "A";

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ENTITY_ID", nullable = false)
    @NotNull
    public EntityA getEntityA() {
        return entityA;
    }

    public void setEntityA(EntityA entityA) {
        this.entityA = entityA;
    }

}



@Entity
@DiscriminatorValue("B")
public class EntityMapB extends EntityMap {

    /**
     *
     */
    private static final long serialVersionUID = -8709307036005000705L;

    public static final String DISCRIMINATOR = "B";

    private EntityB entityB;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ENTITY_ID", nullable = false)
    @NotNull
    public EntityB getEntityB() {
        return entityB;
    }

    public void setEntityB(EntityB entityB) {
        this.entityB = entityB;
    }
}

最后我在 EntityA 中有一个映射:

    @OneToMany(cascade=CascadeType.ALL,fetch = FetchType.LAZY, mappedBy = "entityA")
    public List<EntityMapA> getEntityMaps() {
        return entityMaps;
    }

    public void setEntityMaps(List<EntityMapA> entityMaps) {
        this.entityMaps = entityMaps;
    }

现在我有一个 ENTITY_MAP 行,其中 ENTITY_TYPE = "B" 和 ENTITY_ID = "12345" EntityA 的 ID 为“12345”,EntityB 的 ID 为“12345”。

现在,当我加载 ID 为“12345”的 EntityA 时,在 EntityMapA 类型的 getEntityMaps() 中有一个条目,但该 EntityMapA 上的鉴别器值为“B”。

这里出了什么问题?为什么将带有鉴别器“B”的行映射到 EntityMapA 实体?

是不是因为我在父类上将 EntityId 映射了两次(一次使用 @Column(name="ENTITY_TYPE",insertable=false,updatable=false),然后再次将每个 JoinColumn 映射到实际实体?

更新 顺便说一句,EntityA 集合中列出的 EntityMapA 从未真正创建过。当您尝试加载实体时,您会收到一个异常,告诉您该实体不存在。所以对我来说看起来像是 Hibernate 中的一个错误。

【问题讨论】:

    标签: hibernate jakarta-ee jpa


    【解决方案1】:

    问题在于您使用同一列来映射两个不同的关联。 AFAIK,这是不支持的。

    这实际上是一件好事,因为使用两个单独的列来引用不同的东西要干净得多。例如,它允许在这些列上定义 FK 约束,这在您当前的解决方案中是不可能的,因为该列根据行包含 EntityA 或 EntityB 的 ID。

    【讨论】:

    • 我仍然认为这是一个错误。将鉴别器设置为 B 的行永远不应创建 EntityMapA。
    • 这不是 Hibernate 中的错误,它是一个有问题的映射,正如已经向您指出的那样。正确的映射是将EntityMap上的关联映射为EntityMap。如果需要,您可以在 EntityMapA 和 EntityMapB 上使用协变返回类型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-08
    • 1970-01-01
    • 2014-04-20
    • 1970-01-01
    • 2016-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多