Почему QueryDSL или HQL изменяют условие ON на WITH?
- Я использую библиотеку QueryDSL
- Версия Hibernate 5.4.33
- БД PostgreSQL
Есть два класса сущностей, связанных отношением @OneToMany (опускаю очевидные аннотации Lombok, генераторов ключей и т.д., чтобы не писать лишнего)
@Entity
@Table(name = "products")
public class Product {
@Id
private UUID guid;
//Название продукта
private String name;
//используется ли продукт
private Boolean used;
@OneToMany //fetchType lazy по умолчанию
@JoinColumn(name = "product_guid")
private List<Link> links = new ArrayList<>();
//доп. поля....
}
@Entity
@Table(name = "link")
public class Link {
@Id
private UUID guid;
@Column(name = "product_guid")
private UUID productGuid;
//канал ссылки (WEB/MOBILE)
private Channel channel;
//доп. поля....
}
Для составления запросов используется JpaQueryFactory из библиотеки query-dsl-jpa.
@Bean
public JPAQueryFactory jpaQueryFactory(@Autowired EntityManager em) {
return new JPAQueryFactory(JPQLTemplates.DEFAULT, em);
}
Далее реализация репозитория продуктов, BaseRepositoryImpl имеет поля QProduct.product, QLink.link.
@Repository
public class ProductRepositoryImpl extends BaseRepositoryImpl<Product, UUID> implements ProductRepository {
public ProductRepositoryImpl(EntityManager em,
JPAQueryFactory jpaQueryFactory) {
super(Product.class, em, jpaQueryFactory, QProduct.product);
}
//Проблемный запрос
@Override
public List<Product> findAllProductsWithLinks(@NotNull List<String> names, Channel channel) {
Predicate predicate =
product.name.in(names)
.and(product.used.isTrue())
.and(link.channel.isNull()
.or(link.channel.eq(channel))
);
return queryFactory
.select(product)
.from(product)
.where(predicate)
.leftJoin(product.links, link)
.on(link.channel.eq(channel))
.fetchJoin()
.distinct()
.fetch();
}
}
Хотелось бы одним запросом без ленивой подгрузки вытащить записи продуктов и связанных с ними линками, при этом продукты, у которых отсутствуют линки по условию соединения таблиц ON l.channel = ?
так же должны приходить. Но при выполнении запроса получаю ошибку: Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: with-clause not allowed on fetched associations;
Перерыв поисковики я нашел более менее подходящий совет:
https://github.com/querydsl/querydsl/pull/2604 - подставить в конструктор JpaQueryFactory JPQLTemplates.DEFAUL, так как в этом классе метод public boolean isWithForOn()
возвращает false
. Но это не помогло.
Я проходился дебагом до использования метода isWithForOn(), querydsl формирует запрос с условием ON, но где-то в недрах hibernate видимо происходит замена ON на WITH.
Хотелось бы понять, почему именно это происходит? Можно ли это как-то исправить, или подойдет реализация только с ленивой подгрузкой? Изменять fetchType на EAGER для линков тоже не нужно, так как где-то есть запросы, где они вообще не используются.
Спасибо!