JPA Criteria API:左联接,用于可选关系 [英] JPA Criteria API: LEFT JOIN for optional relationships

查看:131
本文介绍了JPA Criteria API:左联接,用于可选关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我基本上是第一次使用Criteria API.这是关于对通用构建器的查询进行抽象处理:

public TypedQuery<T> newQuery( Manager<?,T> manager )
{
    CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();

    Class<T> genericClass = ( Class<T> ) ( ( ParameterizedType ) manager.getClass().getGenericSuperclass() ).getActualTypeArguments()[1];

    CriteriaQuery<T> criteriaQuery = builder.createQuery( genericClass );
    Root<T> root = criteriaQuery.from( genericClass );

    ...
}

默认情况下,调用criteriaQuery.from( genericClass );会为在实体上找到的所有关系生成SQL INNER JOIN.这是一个问题,因为每个关系都是空的(DB NULL或不使用外键且引用无效的DB),这些实体将在结果列表中丢失,从而有效地产生了错误的搜索结果.

可以在此处找到示例: JPA标准查询Path.get左联接是否可能

对于由此类/方法实例化的查询,我想发生的事情是实体上的所有关系(这里为genericClass)都映射为optional = true

@ManyToOne( FetchType.EAGER, optional = true )
@JoinColumn( name = "CLOSE_USER_ID", referencedColumnName = "USER_ID" )
private User              closer;

生成SQL LEFT (OUTER) JOIN而不是INNER JOIN.

问题:

是否有标准的JPQ方法来完成此任务?如果是这样,怎么办?

PS:通常没有办法事先知道具体的类型,所以我可能能够实现的唯一方法是使用某种元模型并手动生成联接(我想避免这种情况) ).


我们正在使用EclipseLink 2.3

解决方案

.from(class)并非对所有关系都使用INNER联接,它仅查询类.

仅当您使用join()或fetch()API时,才会查询关系,若要使用外部连接,请对JoinType.LEFT使用join().

https://en.wikibooks.org/wiki/Java_Persistence/Criteria#Join

我不确定如果不调用join(),为什么会看到联接.一些JPA提供程序会自动加入以获取所有EAGER关系,这可能就是您看到的.尽管总是很奇怪,但也许您的JPA提供者有能力将其配置为不执行此操作,否则您可以将关系设为LAZY.

I'm using the Criteria API basically the first time. It's about abstracting queries for a generic builder:

public TypedQuery<T> newQuery( Manager<?,T> manager )
{
    CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();

    Class<T> genericClass = ( Class<T> ) ( ( ParameterizedType ) manager.getClass().getGenericSuperclass() ).getActualTypeArguments()[1];

    CriteriaQuery<T> criteriaQuery = builder.createQuery( genericClass );
    Root<T> root = criteriaQuery.from( genericClass );

    ...
}

The call criteriaQuery.from( genericClass ); generates SQL INNER JOIN for all relationships found on the entity by default. This is a problem, because every relationship being null (DB NULL or a DB that doesn't use foreign keys and has an invalid reference) those entities will be missing in the result list, effectively producing wrong search results.

An example can be found here: JPA Criteria query Path.get left join is it possibile

What I'd like to happen for queries instantiated by this class/method is that all relationships on the entity, here genericClass, that are mapped as optional = true

@ManyToOne( FetchType.EAGER, optional = true )
@JoinColumn( name = "CLOSE_USER_ID", referencedColumnName = "USER_ID" )
private User              closer;

to generate an SQL LEFT (OUTER) JOIN instead of INNER JOIN.

Question:

Is there standard JPQ way to get this done? If so, how?

PS: there's generally no way to know the concrete type beforehand, so the only way I might be able to achieve what I need is to use the metamodel of some sort and generate the joins manually (which I'd like to avoid).


We are using EclipseLink 2.3

解决方案

.from(class) does not use an INNER join for all relationships, it only queries the class.

A relationship will only be queried if you use the join() or fetch() API, to use an outer join use join() with a JoinType.LEFT.

https://en.wikibooks.org/wiki/Java_Persistence/Criteria#Join

I'm not sure why you are seeing joins if you are not calling join(). Some JPA providers automatically join fetch all EAGER relationships, this may be what you are seeing. I have always though this odd, perhaps your JPA provider has a away to be configured not to do this, or you can make the relationships LAZY.

这篇关于JPA Criteria API:左联接,用于可选关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆