1

単一のテーブルを使用する JPA クラス階層で奇妙な動作が発生しました。基本的に、両方とも EntityMap を拡張する 2 つのエンティティ EntityMapA と EntityMapB があります。識別子の値は「ENTITY_TYPE」で、EntityMapA の場合は A、EntityMapB の場合は B です。どういうわけか、識別子の値が 'B' に設定されているタイプ EntityMapA のオブジェクトを取得します!

JPA プロバイダーとして Hibernate 3.3 を使用しています。

コードは次のとおりです。

@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_TYPE = "B" および ENTITY_ID = "12345" の ENTITY_MAP 行があります。ID "12345" を持つ EntityA と同じ ID "12345" を持つ EntityB の両方があります。

ID「12345」でEntityAをロードすると、タイプEntityMapAのgetEntityMaps()に1つのエントリがありますが、そのEntityMapAの識別子の値は「B」です。

ここで何がうまくいかないのですか?識別子 'B' を持つ行が EntityMapA エンティティにマップされるのはなぜですか?

EntityId を親クラスで 2 回 (1 回は @Column(name="ENTITY_TYPE",insertable=false,updatable=false) で) マップし、次に JoinColumn ごとに実際のエンティティにマップするためですか?

更新 ところで、EntityA のコレクションにリストされている EntityMapA は、実際には作成されません。エンティティを読み込もうとすると、そのエンティティが存在しないことを示す例外が発生します。だから私にはHibernateのバグのように見えます。

4

1 に答える 1

2

問題は、同じ列を使用して 2 つの異なる関連付けをマップすることです。私の知る限り、これはサポートされていません。

2 つの別々の列を使用して異なるものを参照する方がはるかにクリーンなので、これは実際には良いことです。これらの列に FK 制約を定義できます。たとえば、列は行に応じて EntityA または EntityB の ID を保持するため、現在のソリューションでは不可能です。

于 2012-06-15T13:55:29.917 に答える