JPA标准:从实体层次结构进行投影时,左外部联接而不是内部联接

问题描述

鉴于我有1个父实体和2个子实体:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Notification {

    protected Long id;
    protected Long code;

    protected Notification() {
    }
}

@Entity
@PrimaryKeyJoinColumn(name = "NOTIFICATION_ID")
public class Sms extends Notification {

    private String phoneNumber;
    private String smsText;

    public Sms() {
    }
}

@Entity
@PrimaryKeyJoinColumn(name = "NOTIFICATION_ID")
public class Push extends Notification {

    private String application;
    private String pushText;
    
    public Push() {
    }
}

我想使用JPA标准API进行投影,如下所示:

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<NotificationSummary> query = builder.createquery(NotificationSummary.class);
Root<Notification> root = query.from(Notification.class);

query.select(builder.construct(NotificationSummary.class,root.get("code"),builder.treat(root,Sms.class).get("smsText"),Push.class).get("pushText"),Sms.class).get("phoneNumber"),Push.class).get("application")
));

class NotificationSummary {

    private final Long code;
    private final String smsText;
    private final String pushText;
    private final String phoneNumber;
    private final String application;

    public NotificationSummary(Long code,String smsText,String pushText,String phoneNumber,String application) {
        this.code = code;
        this.smsText = smsText;
        this.pushText = pushText;
        this.phoneNumber = phoneNumber;
        this.application = application;     
    }
}   

执行它会生成SQL查询

select
    notificati0_.code as col_1_0_,notificati0_3_.sms_text as col_5_0_,notificati0_2_.push_text as col_6_0_,notificati0_3_.phone_number as col_7_0_,notificati0_2_.application as col_8_0_ 
from
    notification notificati0_ 
inner join
    push notificati0_2_ 
        on notificati0_.id=notificati0_2_.notification_id 
inner join
    sms notificati0_3_ 
        on notificati0_.id=notificati0_3_.notification_id

我希望它将是外部联接。

我可以以某种方式将其更改为外部联接而不是内部联接吗?

解决方法

不幸的是,这是不可能的,因为HQL中的df=df.replace(regex='[^\w]',value='') print(df) State City 0 AK Yakutat 1 AK Apache 当前会导致内部联接,因为JPA规范在语义上还不太清楚。 IMO可能会有不同的解释,但这就是现在。

在HQL中,您实际上可以省略ggplot(dataM[dataM$category=="m" & dataM$order=="RAN",],aes(x=nbr,y=value,fill=net)) + geom_ribbon(aes(ymin=0,ymax=value),alpha=0.3)+ scale_fill_brewer(palette="Set1") 来隐式访问子类型属性,这将导致左联接,就像您期望的那样。如果您不想在HQL中重写查询,则可以使用本质上可以呈现为JPQL / HQL的其他JPA Criteria实现。 Blaze-Persistence是一个在JPA / Hibernate之上运行的库,它支持许多高级SQL功能,同时仍处于JPA模型领域。这是使用JPA Criteria实现的快速入门的链接:https://github.com/Blazebit/blaze-persistence#jpa-criteria-api-quick-start

您还需要一些dependencies,但由于您要创建投影,因此您可能还喜欢Blaze-Persistence Entity-Views,它允许您以更具声明性的方式创建投影。您的用例可能与Entity-Views相似:

TREAT