1

ID とバージョン フィールドを含む ID が埋め込まれたエンティティがあります。

@Entity
@Table(name = "MyEntity")
public class MyEntity {
    @EmbeddedId
    private MyEntityEmbeddedId compositeId;

    @Column
    private DateTime begin;

    @Column
    private DateTime end;

}

@Embeddable
public class MyEntityEmbeddedId {
    @Column(name = "ID", nullable = false, updatable = false)
    private Long id;

    @Column(name = "VERSION", nullable = false, updatable = false)
    private Long version;

    public MyEntityEmbeddedId () {}

}

エンティティのフィルターとしていくつかの基準を使用してデータベースにクエリを実行する必要があります。たとえば、日付と ID のリストを指定してリクエストします。

List<MyEntity> listEntities = getMyEntities(List<Long> ids, DateTime date);

ID が ID リストにあり、指定された日付が MyEntity の「開始」と「終了」の日付プロパティの間にあるすべてのエンティティを取得するクエリの作成に成功しました。

ただし、このエンティティには複合 ID があるため、リクエスト パラメータに対応する可能性のある同じ「ID」を持つ MyEntity が多数存在します。同じ「id」を持つものが多数ある場合、「バージョン」番号が最も高い MyEntity を取得する別のフィルターを追加したいと考えています。

データベースにある可能性のあるものの例を次に示します。

+------+-----------+--------------------+
| id   | version   | began    |   end   |
+------+-----------+--------------------+
| 1    | 1         | ...      |   ...   |
| 1    | 2         | ...      |   ...   |
| 1    | 3         | ...      |   ...   |
| 2    | 1         | ...      |   ...   |
| 2    | 2         | ...      |   ...   |
+------+-----------+--------------------+

以前のすべてのデータベース レコードがフィルタリング パラメーターに対応している場合、対応する ID のバージョン番号が最大のものであるため、次の 1 つだけを取得する必要があります。

+------+-----------+--------------------+
| id   | version   | began    |   end   |
+------+-----------+--------------------+ 
| 1    | 3         | ...      |   ...   |
| 2    | 2         | ...      |   ...   |
+------+-----------+--------------------+

現在、私はリクエストを行っていますが、サービス内のメソッド内でバージョンをフィルタリングしていますが、バージョンがデータベース リクエストですでにフィルタリングされている場合はそれを好みます。バージョンがフィルター処理された後に破棄されるレコードを取得する必要はありません。

JPA Criteria-API で自己結合する方法を探しています。

次のリンクでは、JPA Criteria-API で提案された SQL をどのように変換するのか疑問に思っているため、受け入れられた回答が私の問題を解決するようです。

SQL は、列に最大値を持つ行のみを選択します

select yt1.*
from yourtable yt1
left outer join yourtable yt2
on (yt1.id = yt2.id and yt1.rev < yt2.rev)
where yt2.id is null;

私の問題は、結合を作成しようとしているときです。結合の 2 番目のエンティティにリンクする最初のエンティティからプロパティを提供する必要があります。自己結合を作成したいので、エンティティ内にそれ自体を指すプロパティはありません。

Join<MyEntity, MyEntity> selfJoin = root.join(MyEntity_.???);

ご覧のとおり、MyEntity の静的メタモデルを使用しています。JPA Criteria-API で自己結合する方法はありますか?

または、他のスタックオーバーフローの質問で提案されているように、自己左結合以外にリクエストを作成する別の方法があるかもしれません。

Spring Data JPA 仕様を使用して、Predicate でクエリを作成しています。次に、findAll(Specification) が使用されます。withIds() と withDate() の述語を生成するための仕様メソッドが他に 2 つあります。これにより、ユーザーから提供された「未定の数」のパラメーターを使用してクエリを作成できました。

public static Specification<MyEntity> withIdAndDate(final List<Long> ids, 
        final DateTime date) {
    return new Specification<MyEntity>() {

        @Override
        public Predicate toPredicate(Root<MyEntity> root, CriteriaQuery<?> query, 
                CriteriaBuilder cb){
            Join<MyEntity, MyEntity> selfJoin = root.join();
            Predicate pIds = withIds(ids).toPredicate(root, query, cb);
            Predicate pDate = withDate(date).toPredicate(root, query, cb);

            return cb.and(pIds, pDate);
        }

    };
}

あなたの助けと提案に感謝します!

4

1 に答える 1