问题
Consider the following model
@Entity
// JPA and JAXB annotations here
public class Employee implements Serializable {
// other fields, annotations, stuffs
...
@ElementCollection(fetch = FetchType.LAZY,
targetClass = Address.class)
@CollectionTable(name = "employee_address",
schema = "hris",
joinColumns = @JoinColumn(name = "employee_id",
nullable = false,
referencedColumnName = "employee_id",
foreignKey = @ForeignKey(ConstraintMode.CONSTRAINT)))
protected Set<Address> addresses;
// setters, getters
...
}
@Embeddable
// JAXB annotations here
public class Address implements Serializable {
// fields, setters, getters
}
The Address
class is annotated with @Embeddable
annotation, and the Employee
class has an embedded element collection of addresses
. The element collection's fetch
is set to FetchType.LAZY
. Now, I would like to create a @NamedQuery
that would retrieve all employees with addresses eagerly initialized. Knowing that JOIN FETCH
will only work with entity collections annotated with @OneToMany
or @ManyToMany
based on JPA 2.1, how would I create a valid JPQL
query that would allow me to eagerly retrieve embedded element collections?
回答1:
In the JPA 2.1 specification (JSR 338) I cannot find any hint that fetch joins only work on entity relationships (but not embeddables). JSR 338, section 4.4.5.3 even states:
A
FETCH JOIN
enables the fetching of an association or element collection as a side effect of the execution of a query.
As another hint the following minimal example (essentially resembling yours) executed with Hibernate 4.3.11 as JPA provider results in a single query:
Address embeddable:
@Embeddable public class Address { private String city; }
Employee entity:
@Entity public class Employee {
@Id private Long id;
@ElementCollection(fetch = FetchType.LAZY)
@CollectionTable(name = "address",
joinColumns = @JoinColumn(name="employee_id"))
private Set<Address> addresses;
}
JPQL Query:
em.createQuery("select e from Employee e join fetch e.addresses").getResultList();
Resulting SQL query:
select
employee0_.id as id1_1_,
addresses1_.employee_id as employee1_1_0__,
addresses1_.city as city2_5_0__
from
Employee employee0_
inner join
address addresses1_ on employee0_.id=addresses1_.employee_id
So the above JPQL query seems to solve your problem.
回答2:
By the way, more effective way might be not to use join, but subselect
@Fetch(FetchMode.SUBSELECT)
@BatchSize(size=500)
it makes two selects, instead of one, but doesn't produce so much ambiguity.
来源:https://stackoverflow.com/questions/33773079/jpa-how-to-fetch-eagerly-an-embedded-element-collection