Hibernate JPA标准:从实体层次结构进行投影时,使用左外部联接而不是内部联接
假设我有1个父实体和2个子实体:Hibernate JPA标准:从实体层次结构进行投影时,使用左外部联接而不是内部联接,hibernate,jpa,spring-data-jpa,jpa-2.0,criteria-api,Hibernate,Jpa,Spring Data Jpa,Jpa 2.0,Criteria Api,假设我有1个父实体和2个子实体: @Entity @Inheritance(strategy = InheritanceType.JOINED) public abstract class Notification { protected Long id; protected Long code; protected Notification() { } } @Entity @PrimaryKeyJoinColumn(name = "NOTIFIC
@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"),
builder.treat(root, Push.class).get("pushText"),
builder.treat(root, Sms.class).get("phoneNumber"),
builder.treat(root, 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;
}
}
我想它会留在外面
我是否可以将其更改为左外部联接而不是内部联接?这是不可能的,因为HQL中的
TREAT
目前导致内部联接,因为JPA规范在语义上不是很清楚。在我看来,这可能会有不同的解释,但这就是现在的情况
在HQL中,您实际上可以省略TREAT
来隐式访问子类型属性,这将导致左连接,就像您所期望的那样。如果您不想在HQL中重写您的查询,那么您可以使用一个不同的JPA标准实现,它本质上呈现给JPQL/HQL。Blaze Persistence是一个在JPA/Hibernate之上工作的库,它支持许多高级SQL特性,同时保持在JPA模型的范围内。以下是使用JPA标准实施的快速入门链接:
您还需要一些,但由于您想要创建投影,您可能也喜欢它,它允许您以更具声明性的方式创建投影。对于实体视图,您的用例可能如下所示:
@EntityView(Notification.class)
public interface NotificationSummary {
Long getCode();
@Mapping("TREAT(this AS Sms).smsText")
String getSmsText();
@Mapping("TREAT(this AS Push).pushText")
String getPushText();
@Mapping("TREAT(this AS Sms).phoneNumber")
String getPhoneNumber();
@Mapping("TREAT(this AS Push).application")
String getApplication();
}
非常感谢,关于HQL无需治疗即可工作的经验教训。HQL查询现在适用于我。稍后我将尝试blaze持久性项目。
@EntityView(Notification.class)
public interface NotificationSummary {
Long getCode();
@Mapping("TREAT(this AS Sms).smsText")
String getSmsText();
@Mapping("TREAT(this AS Push).pushText")
String getPushText();
@Mapping("TREAT(this AS Sms).phoneNumber")
String getPhoneNumber();
@Mapping("TREAT(this AS Push).application")
String getApplication();
}