I'm using JPA2 Criteria API with Hibernate. The simplified database schema is as follows
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "order", orphanRemoval = true)
private Set<OrderItem> items = new LinkedHashSet<>();
@OneToMany(cascade = CascadeType.ALL, mappedBy = "order", orphanRemoval = true)
private Set<OrderTransaction> transactions = new LinkedHashSet<>();
Corresponding OrderItem
and OrderTransaction
have @ManyToOne
relation with Order
I'm using following query to fetch Order with all of its descendants
public List<Order> findByIds(Collection<Long> ids) {
if (ids.isEmpty()) return Collections.emptyList();
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Order> query = builder.createQuery(Order.class);
Root<Order> root = query.from(Order.class);
root.fetch("items", JoinType.LEFT);
root.fetch("transactions", JoinType.LEFT);
Predicate whereId = root.get("id").in(ids);
TypedQuery<Order> typedQuery = entityManager.createQuery(
query
.select(root)
.where(whereId)
.distinct(true)
);
return typedQuery.getResultList();
}
The resulting query is
select distinct order0_.id as id1_75_0_,
items1_.order_id as order_i28_74_0__,
items1_.id as id1_74_0__,
transactio2_.order_id as order_i13_80_1__,
transactio2_.id as id1_80_1__
from Order order0_
left outer join OrderItem items1_ on order0_.id = items1_.order_id
left outer join OrderTransaction transactio2_ on order0_.id = transactio2_.order_id
where order0_.id in (?, ?)
I'm trying to achieve fetch join but with multiple queries. I'm expecting to get entirely loaded entity out of the Repository. Lazy loading is not an option. So expected output is 3 queries, one for fetching Order
, and the other two for OrderItem
and OrderTransaction
. Batching would be beneficial but it is not necessary.
What I tried so far
@Fetch(FetchMode.SELECT)
to each OneToMany
. It didn't change anything. I think It works in pair with lazy loading, not with join fetch I'm doing.Solutions I came up with
Is there Hibernate solution for this problem?
Came up with satisfying solution.
I'm using @Fetch(FetchMode.SUBSELECT)
. I remove all the OneToMany
fetches from the query with a custom utility, and initialize collections via reflection. That way I do get 3 queries and entities are entirely initialized leaving the Repository
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.