休止状態にJPA基準のAPIとN + 1を取り除く方法

ドミトリーSenkovich:

私はJPAの基準APIにHibernateの基準APIを使用してから私たちのDAOを移行しています。私はいくつかのクラスを持っている@ManyToOneが:

@Entity
@Table(name = "A_TABLE", schema="SCHEMA_NAME")
public class A {
    @ManyToOne
    @JoinFormula("(SELECT * FROM (SELECT B.B_ID FROM SCHEMA_NAME.B_TABLE B WHERE B.A_ID = B_ID AND (B.B_CODE = '1' OR B.B_CODE = '2') ORDER BY B.B_CREATED_TIMESTAMP DESC) WHERE ROWNUM = 1)")
    private B b1;
    @ManyToOne
    @JoinFormula("(SELECT * FROM (SELECT B.B_ID FROM SCHEMA_NAME.B_TABLE B WHERE B.A_ID = B_ID AND (B.B_CODE = '3' OR B.B_CODE = '4') ORDER BY B.B_CREATED_TIMESTAMP DESC) WHERE ROWNUM = 1)")
    private B b2;
    ...
}

@Entity
@Table(name = "B_TABLE", schema="SCHEMA_NAME")
public class B {

}

クエリで私が使用しているJoinType.LEFTデフォルトで生成さを取り除くために、CROSS JOINさん:

if (LEFT_OUTER_JOIN_ENTITIES.contains(field)) {
    path = ((From) path).join(field, JoinType.LEFT);
} else {
    path = path.get(field);
}

私は右の結果を得ている、すべてABレコードが正しく取得されます。ただし、移行後に私は、n + 1問題を取得しています:すべてBのレコードが使用しているにもかかわらず1対1を取得しているLEFT OUTER JOIN「が生成クエリでね。(Hibernateの基準APIを使用する場合)以前にHibernateは、N + 1は、同じ生成されたSQLに参加せずにクエリを満たすことができました。

任意のアイデアや助けをありがとう!

UPDATEの使用例として、if-else「b1.fieldName」で検索のための上記の私は、次のようになるだろう。

criteriaBuilder.equal(root.join("b1", JoinType.LEFT).get("someFiled"), 42)
ヴラッド・ミホールセア:

N + 1問題がから来ているデフォルトEAGERフェッチ戦略@ManyToOne団体。

だから、あなたはに切り替える必要がありFetchType.LAZY、このように、:

@ManyToOne(fetch = FetchType.LAZY)
@JoinFormula("(SELECT * FROM (SELECT B.B_ID FROM SCHEMA_NAME.B_TABLE B WHERE B.A_ID = B_ID AND (B.B_CODE = '1' OR B.B_CODE = '2') ORDER BY B.B_CREATED_TIMESTAMP DESC) WHERE ROWNUM = 1)")
private B b1;

@ManyToOne(fetch = FetchType.LAZY)
@JoinFormula("(SELECT * FROM (SELECT B.B_ID FROM SCHEMA_NAME.B_TABLE B WHERE B.A_ID = B_ID AND (B.B_CODE = '3' OR B.B_CODE = '4') ORDER BY B.B_CREATED_TIMESTAMP DESC) WHERE ROWNUM = 1)")
private B b2;

あなたは自動的にあなたのアプリケーションの他の部分に影響を与える可能性があることを自動的N + 1問題を検出したい場合は、チェックアウトこの記事を

あなたが基準APIとの関連を即時にフェッチする必要がある場合は、使用する必要がありますfetch代わりにjoin

if (LEFT_OUTER_JOIN_ENTITIES.contains(field)) {
    path = ((From) path).fetch(field, JoinType.LEFT);
} else {
    path = path.get(field);
}

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=212889&siteId=1