単一のテーブルを使用する 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のバグのように見えます。