12

状況

DiscriminatorColumn単一テーブル継承用に構成された、を持つエンティティがあります。

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE")
public class ContainerAssignment{
...
}

'ContainerAssignment'には、別のエンティティへの参照があります。

@JoinColumn(name="CONTAINER_ID")
private Container container;

コンテナにはContainerAssignment、各TYPEの1つが含まれる場合があります。これは、テーブルの主キーがとContainerAssignmentによって定義されることを意味します。CONTAINER_IDTYPE

ContainerAssignmentいくつかのサブクラスがあります。

@Entity
@DiscriminatorValue("SOME_TYPE")
public class SomeTypeOfContainerAssignment extends ContainerAssignment{
...
}

SomeTypeOfContainerAssignment特定のに対して1つのインスタンスのみが存在しますCONTAINER_ID

問題

JPA@IdをContainerAssignmentテーブルのContainerとして定義すると、実行できますentityManager.find(SomeTypeOfContainerAssignment.class, containerId)。これはすばらしいことです。これは、の線に沿って何かを実行しますSELECT * FROM CONTAINER_ASSIGNMENT WHERE CONTAINER_ID = 1 AND TYPE = 'SOME_TYPE';@DiscriminatorValue("SOME_TYPE")エンティティに注釈があるため、ここでTYPEチェックが必要であることを認識しています。

ただし、これは、Containerが実際には主キーではないため、ContainerからContainerAssignmentへの逆参照が壊れることを意味します。たとえば、Containerにが含まれている場合、コンテナ@OneToOne(mappedBy=container) private SomeTypeOfContainerAssignment assignment;を読み込むとSELECT * FROM CONTAINER_ASSIGNMENT WHERE CONTAINER_ID = 1;、型チェックなしで、のようなものによって割り当てが読み込まれます。これにより、コンテナのすべての割り当てが与えられ、次に、一見ランダムに見えるものを選択します。タイプが間違っている可能性があります。その場合、例外がスローされます。

代わりに、ContainerAssignmentのJPA@Idをcontainerとtypeを使用した複合IDとして定義すると、ContainerAssignmentのサブクラスへの参照は正常に機能します。

ただし、entityManager.find(SomeTypeOfContainerAssignment.class, containerId)containerIdはIDではないため、実行できません。私がしなければならないentityManager.find(SomeTypeOfContainerAssignment.class, new MyPk(containerId, "SOME_TYPE"))、それはのポイントを打ち負かすようです@DiscriminatorValue("SOME_TYPE")。とにかく検索時にタイプを指定する必要がある場合は、単一のContainerAssignmentエンティティを使用する方がよいでしょう。

質問

単一テーブル継承エンティティのサブクラスへの作業参照を持つ方法はありますか?テーブルの主キーがディスクリミネーター列で複合されている一方EntityManager.findで、主キーの一部だけで参照できる方法はありますか?弁別者ではありませんか?

4

3 に答える 3

0

プロバイダー固有の拡張機能に問題がない場合、Hibernate はアノテーション@DiscriminatorOptionsを提供します。

識別子列が複合主キーの一部であるという問題を解決するのに役立ちました。

于 2020-03-31T14:00:34.457 に答える
0

を拡張Containerする双方向の OneToOne がある場合、オブジェクトフィールドは ではなく で定義およびマッピングする必要があります。SomeTypeOfContainerAssignmentContainerAssignmentContainerAssignmentSomeTypeOfContainerAssignment

public class Container {
    @Id
    private Long id;

    @OneToOne(mappedBy = "container")
    private SomeTypeOfContainerAssignment someTypeOfContainerAssignment;
}

public class ContainerAssignment {
    @Id
    private Long id;
}

public class SomeTypeOfContainerAssignment extends ContainerAssignment {
    @OneToOne
    private Container container;
}

すべてのタイプのコンテナ割り当てが、コンテナとの OneToOne 関連付けを持っている場合、コンテナを次のように定義できます。

public abstract class ContainerAssignment {
    @Id
    private Long id;

    public abstract Container getContainer();
    public abstract void setContainer(Container container);
}

@OneToOne container正直なところ、テーブル内の同じ結合列を使用して各サブクラスのフィールドをマップすることが許可されているかどうかはわかりません。

これはあなたが持つことができる最高のものだと思います。オブジェクト フィールドを基本クラスに配置する場合は、関連付けを OneToMany/ManyToOne 関連付けとして定義する必要があります。

私はあなたがやりたいことが可能だとは思いません.複合 PK を台無しにするつもりはありません.

于 2012-12-10T21:48:43.383 に答える