1

使用单个表的 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" 有一个 ID 为 "12345" 的 EntityA 和一个 ID 为 "12345" 的 EntityB。

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

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

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

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

4

1 回答 1

2

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

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

于 2012-06-15T13:55:29.917 回答