web-dev-qa-db-ja.com

ソーステーブルの定数値に結合条件を持つHibernate / JPA単方向OneToMany

Hibernateアノテーションを使用して、結合を使用した一方向の1対多の関係を表現したいと思います。結合に条件を追加して、sourceテーブル(「1」)の列が定数値に等しい場合にのみ発生するようにします。例えば。

SELECT *
FROM buildings b
LEFT JOIN building_floors bf on bf.building_id = b.id AND b.type = 'OFFICE'

そのクエリのb.type = 'OFFICE'部分を表現したいと思います。

私の質問は、ソーステーブルに条件があることを除いて、これと非常によく似ています。 JPA /定数値でのHibernate結合

Javaエンティティは次のようになります:

@Entity
@Table(name = "buildings")
public class Building {

    @Id
    @Column(name = "id")
    private int id;

    @Column(name = "type")
    private String type;

    @OneToMany(mappedBy = "buildingId",
            fetch = FetchType.EAGER,
            cascade = {CascadeType.ALL},
            orphanRemoval = true)
    @Fetch(FetchMode.JOIN)
    // buildings.type = 'OFFICE'   ????
    private Set<BuildingFloors> buildingFloors;

    // getters/setters
}

@Entity
@Table(name = "building_floors")
public class BuildingFloor {

    @Id
    @Column(name = "building_id")
    private int buildingId;

    @Id
    @Column(name = "floor_id")
    private int floorId;

    @Column(name = "description")
    private String description;

    // getters/setters
}

私はそのプレースホルダーコメントがあるいくつかのことを試しました:

@Whereアノテーション

これはターゲットエンティティに適用されるため、機能しません。

@JoinColumnsアノテーション

@JoinColumns({
        @JoinColumn(name = "building_id", referencedColumnName = "id"),
        @JoinColumn(name = "'OFFICE'", referencedColumnName = "type")
})

次のエラーが発生するため、これは機能しません(わかりやすくするために簡略化):Syntax error in SQL statement "SELECT * FROM buildings b JOIN building_floors bf on bf.building_id = b.id AND bf.'OFFICE' = b.type"

別の@JoinColumnsアノテーション

@JoinColumns({
        @JoinColumn(name = "building_id", referencedColumnName = "id"),
        @JoinColumn(name = "buildings.type", referencedColumnName = "'OFFICE'")
})

単方向のOneToMany関係を使用する場合、referencedColumnNameはソーステーブルからのものであるため、これは機能しません。だから私はエラーを受け取ります:org.hibernate.MappingException: Unable to find column with logical name: 'OFFICE' in buildings

前もって感謝します!

15
rafiss

継承 を使用しないのはなぜですか? (JPAで使用します。Hibernateを直接使用することはありません)

@Entity
@Inheritance
@Table(name = "buildings")
@DiscriminatorColumn(name="type")
public class Building {

    @Id
    @Column(name = "id")
    private int id;

    @Column(name = "type")
    private String type;
}

そして:

@Entity
@DiscriminatorValue("OFFICE")
public class Office extends Building {
    @OneToMany(mappedBy = "buildingId",
        fetch = FetchType.EAGER,
        cascade = {CascadeType.ALL},
        orphanRemoval = true)
    private Set<BuildingFloors> buildingFloors;
}
9
wargre

次の選択でデータベースビューを作成します。

SELECT bf.* FROM building_floors bf JOIN buildings b on bf.building_id = b.id AND b.type = 'OFFICE'

それを通常のエンティティとしてクラスOfficeBuildingFloorsにマップしてから、Buildingクラスで@OneToManyを使用します。

もちろん、そのようなコレクションを変更することはできません。例外を回避するために、OfficeBuildingFloors@Immutableを使用できます。

4
Adrian

フィルタソーステーブルが必要な場合は、@ Loaderアノテーションを使用できます

@Entity
@Table(name = "buildings")
@Loader(namedQuery = "building")
@NamedNativeQuery(name="building", 
    query="SELECT * FROM buildings b"
        + " LEFT JOIN building_floors bf on bf.building_id = b.id"
        + " WHERE b.type = 'OFFICE' AND b.id = ?",
    resultClass = Building.class)
class Building

DB内でも使用できれば、DBでの視点によるアプローチの方がより明確になります。それ以外の場合は、Buildingの名前をフィルタリングを明示的に表す名前に変更します。

言及する別のアプローチ:@ Filter、@ FilterDef。

1
egorlitvinenko

私の意見では、定数パラメーターを使用して特定のアノテーションを配置するのではなく、目標を達成するために特定のクエリを作成する必要があります。 Hibernate以外の別のフレームワークについて言及されていないので、Hibernateでいくつか例を挙げます。 Buildingクラスでは、unidirectionalマッピングは次のようになります。

@OneToMany(fetch = FetchType.Lazy, cascade = {CascadeType.ALL}, orphanRemoval = true)
@JoinTable(name = "building_floors", joinColumns = @JoinColumn(name = "id"), inverseJoinColumns = @JoinColumn(name = "building_id")
private Set<BuildingFloor> buildingFloors;

次に、このようにTypedQueryを使用してデータをフェッチできます。

TypedQuery<Customer> query = getEntityManager().createNamedQuery("select b from building b inner join fetch b.buildingFloors where b.type = 'OFFICE'", Building.class);
List<Building> result = query.getResultList();

私のソリューションはHibernate固有ではありません。実際、これは単純なJPAで実行できます。これがあなたの目標を達成するのに役立つことを願っています。

1
Sukma Wardana