We're using JPA, and when a collection of objects returns from a query, a separate query is executed for each "child" object related through a foreign key.
For example, in our Authorization entity class, we have the following Client object mapped:
@JoinColumn(name = "clientId", referencedColumnName = "clientId")
@ManyToOne (fetch = FetchType.LAZY)
@NotNull(groups = Default.class)
private Client client;
When 10 Authorizations are returned, 10 Client queries are executed. In TopLink, I was able to bring this number to one with the ReadAllQuery class's addBatchReadAttribute() method. According to the TopLink docs, "when any of the batched parts is accessed, the parts will all be read in a single query, this allows all of the data required for the parts to be read in a single query instead of (n) queries."
This worked perfectly, giving us a single query using an IN clause with 10 ids.
What I read about re: JPA pointed me toward a batch join or something like:
hints = {@QueryHint(name = "eclipselink.batch", value = "p.client"), ...
This strategy helps reduce the number of queries,
- but it also gave me more joins, possibly slowing things down (?) on some queries
- and it didn't seem to help as drastically as the TopLink call.
Is there a way to get the strategy that uses a singl开发者_运维知识库e query with IN in the WHERE clause?
Thanks in advance. Dave
Internally the QueryHint "eclipselink.batch" is translated to addBatchAttribute() so the behaviour you see should be identical. Does the JPQL you have created produce the same query as the native TopLink API? It is possible you have Fetch's or additional joins in the JPQL?
EclipseLink supports several types of batch fetching.
See, http://java-persistence-performance.blogspot.com/2010/08/batch-fetching-optimizing-object-graph.html
精彩评论