有する以下の単純化エンティティ:Hibernateでの双方向のオプションの1対1関連付けの1 + nデータベース呼び出しを避けるには?
@MappedSuperclass
public abstract class AbstractEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;
}
@Entity
@Table(name = "t_invoice")
public class Invoice extends AbstractEntity {
@OneToOne(optional = false, fetch = FetchType.EAGER)
@JoinColumn(name = "order_id")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Order order;
}
@Entity
@Table(name = "t_order")
public class Order extends AbstractEntity {
@OneToMany(mappedBy = "order", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@SortNatural
private SortedSet<OrderLine> orderLines = new TreeSet<>();
@OneToOne(optional = true, mappedBy = "order", fetch = FetchType.EAGER)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Invoice invoice;
}
と使用してリポジトリ以下スプリングデータ
public interface InvoiceRepository extends JpaRepository<Invoice, Long> {
List<Invoice> findDistinctByInvoiceDateBetween(LocalDate from, LocalDate until);
}
リポジトリ方法を使用して請求書をフェッチ1 + N SQL文がログに示されているように実行されます。
SELECT DISTINCT i.id, ... FROM t_invoice i WHERE i.invoice_date BETWEEN ? AND ?;
SELECT i.id, ... FROM t_invoice i WHERE i.order_id = ?;
SELECT i.id, ... FROM t_invoice i WHERE i.order_id = ?;
... n
投稿者this回答私は1対1のオプションのアソシエートHibernateはn個のデータベース呼び出しを行って、オプションの請求書がnullかどうかを判断する必要があります。 私に混乱を招くのは、Hibernateがすでに質問のインボイスを初期クエリで取得していることです。なぜ、すでにフェッチされた請求書のデータを使用しないのですか?
また、@ NamedEntityGraphと@NamedSubgraphを使用してn個の呼び出しを避け、熱心に請求書を順番に取り込もうとしました。
したがって、今請求書エンティティは次のようになります。
@Entity
@NamedEntityGraph(
name = Invoice.INVOICE_GRAPH,
attributeNodes = {
@NamedAttributeNode(value = "order", subgraph = "order.subgraph")
},
subgraphs = {
@NamedSubgraph(name = "order.subgraph", attributeNodes = {
@NamedAttributeNode("invoice"),
@NamedAttributeNode("orderLines")
}),
}
)
@Table(name = "t_invoice")
public class Invoice extends AbstractEntity {
@OneToOne(optional = false, fetch = FetchType.EAGER)
@JoinColumn(name = "order_id")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Order order;
}
とリポジトリ内のメソッドは次のようになります。
@EntityGraph(value = Invoice.INVOICE_GRAPH, type = EntityGraph.EntityGraphType.LOAD)
List<Invoice> findDistinctByInvoiceDateBetween(LocalDate from, LocalDate until);
しかし、それはまだ、n個のデータベースでも最初のSQL SELECT句ものの呼び出しを行います表示される2倍の請求書データが表示されます。
SELECT DISTINCT
invoice0_.id AS id1_13_0_,
order1_.id AS id1_14_2_,
orderlines4_.id AS id1_15_4_,
invoice5_.id AS id1_13_5_,
invoice0_.created AS created2_13_0_,
order1_.created AS created2_14_2_,
orderlines4_.created AS created2_15_4_,
invoice5_.created AS created2_13_5_,
FROM t_invoice invoice0_ ... more join clausules ...
WHERE invoice0_.order_id = order1_.id AND (invoice0_.invoice_date BETWEEN ? AND ?)
だから私はwonderiです注文書に請求書を取り込むための追加の呼び出しを避ける方法は?