私はeclipselink2.6.4を使用しており、次のエンティティがあります
@Entity
@Table(name = "articles")
public class Article {
@Id
@Column(name = "id")
private Integer id;
@Column(name = "title")
private String title;
@OneToMany(fetch = FetchType.EAGER,mappedBy = "article")
@BatchFetch(BatchFetchType.IN)
private List<Author> authors
//+ setters and getters
}
@Entity
@Table(name = "authors")
public class Author {
@Id
@Column(name = "id")
private Integer id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "articleId")
private Article article;
@Column(name = "surname")
private String surname;
//+setters and getters
}
そして、これは私が著者と一緒にすべての記事を読むために使用するコードです:
String queryString="SELECT e FROM Article e";
Query query = em.createQuery(queryString);
query.setHint("eclipselink.batch.type", "IN");
query.setHint("eclipselink.batch", "e.authors");
query.setFirstResult(position);
query.setMaxResults(amount);
List<Article> items=query.getResultList();
DBには3つの記事があり、すべての記事に2人の著者がいます。そして、これらはeclipselinkが実行するクエリです。
SELECT id AS a1, title AS a2 FROM articles LIMIT ? OFFSET ? bind => [2 parameters bound]
SELECT id, surname, articleId FROM authors WHERE (articleId IN (?,?,?)) bind => [3 parameters bound]
SELECT id, title FROM articles WHERE (id IN (?,?)) bind => [2 parameters bound]
SELECT id, surname, articleId FROM authors WHERE (articleId = ?) bind => [1 parameter bound]
SELECT id, surname, articleId FROM authors WHERE (articleId = ?) bind => [1 parameter bound]
なぜそんなに多くのクエリ?私は2つのクエリだけを期待しています。私の間違いは何ですか?
編集
私はさらに2つのテストを行いました:
@BatchFetch(BatchFetchType.IN)
フィールド作成者のArticleクラスでのみ注釈を使用しました(クエリにヒントを追加しませんでした)注釈は使用しませんでした@BatchFetch(BatchFetchType.IN)
が、クエリで2つのヒントを使用しました。
String queryString = "SELECT e FROM Article e"; クエリクエリ= em.createQuery(queryString); query.setHint( "eclipselink.batch.type"、 "IN"); query.setHint( "eclipselink.batch"、 "e.authors"); query.setFirstResult(0); query.setMaxResults(10); リストitems = query.getResultList();
表記事のデータ:
| id | title |
-----------------
| 1 | article1 |
| 2 | article2 |
| 3 | article3 |
テーブル作成者のデータ:
| id | articleId | surname |
------------------------------
| 1 | 1 | Author1 |
| 2 | 1 | Author2 |
| 3 | 2 | Author3 |
| 4 | 2 | Author4 |
| 5 | 3 | Author5 |
| 6 | 3 | Author6 |
各テストでは、6つのクエリが実行されます。
SELECT id AS a1, title AS a2 FROM articles LIMIT ? OFFSET ? bind => [2 parameters bound]
SELECT id, surname, articleId FROM authors WHERE (articleId IN (?,?,?)) bind => [3 parameters bound]
SELECT id, title FROM articles WHERE (id = ?) bind => [1 parameter bound]
SELECT id, surname, articleId FROM authors WHERE (articleId = ?) bind => [1 parameter bound]
SELECT id, title FROM articles WHERE (id = ?) bind => [1 parameter bound]
SELECT id, surname, articleId FROM authors WHERE (articleId = ?) bind => [1 parameter bound]
バッチフェッチを設定する方法は2つあります。
@BatchFetch(BatchFetchType.IN)
query.setHint(QueryHints.BATCH, column);
query.setHint(QueryHints.BATCH_TYPE, BatchFetchType.IN);
あなたの場合、Author
テーブルに注釈を追加したようですが、ヒントを使用したクエリはテーブルで実行されArticle
ます。私はこれの背後にある論理全体を知りませんが、私は提案します:
@Entity
@Table(name = "articles")
public class Article {
@Id
@Column(name = "id")
private Integer id;
@Column(name = "title")
private String title;
@OneToMany(mappedBy = "article", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@BatchFetch(BatchFetchType.IN)
private List<Author> authors
//+ setters and getters
}
@Entity
@Table(name = "authors")
public class Author {
@Id
@Column(name = "id")
private Integer id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "articleId")
private Article article;
@Column(name = "surname")
private String surname;
//+setters and getters
}
または
ヒント付きのクエリのみを使用して、そのアノテーションを使用しないでください。
String queryString="SELECT e FROM Article e";
Query query = em.createQuery(queryString);
query.setHint("eclipselink.batch.type", "IN");
query.setHint("eclipselink.batch", "e.authors");
query.setFirstResult(position);
query.setMaxResults(amount);
List<Article> items=query.getResultList();
もう1つ:JPA 2.0仕様から、デフォルトは次のようになります。
OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER
Eclipseリンクは同じものを使用します:
OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER
@OneToManyは(fetch = FetchType.EAGER)である必要があり、@ ManyToOneは(fetch = FetchType.LAZY)である必要があります。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加