在嵌入对象上使用 CriteriaBuilder

问题描述 投票:0回答:2

我尝试将

@Embeddable
CriteriaBuilder
一起使用,根据嵌入属性过滤父级
Entity
的结果。我使用 Eclipse Link 生成元数据类。

这是嵌入的类/实体:

@Embeddable
public class Stamp implements Serializable {

   @Basic()
   @Column(name = "stamp_year", nullable = false)
   private int year;

父类有

Stamp
作为成员:

@Entity(name = "Message")
public class Message implements Serializable {

   @Embedded
   private Stamp stamp = new Stamp();

现在此代码应该使用

Message
类并根据嵌入的类属性年份过滤结果:

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Message> cq = cb.createQuery(Message.class);
    Root<Message> root = cq.from(Message.class);
    Predicate p = cb.conjunction();
    p = ??????
    cq.where(p);
    TypedQuery<Message> tq = em.createQuery(cq);
    List<Message> messages = tq.getResultList();

在第 5 行,如何访问查询的 Message->Stamp->Year 元素?

这是生成的元模型类:

@StaticMetamodel(Message.class)
public class Message_ { 

    public static volatile SingularAttribute<Message, Stamp> stamp;

和:

@StaticMetamodel(Stamp.class)
public class Stamp_ { 

   public static volatile SingularAttribute<Stamp, Integer> year;

注意:为了代码清晰起见,我删除了所有不相关的信息,但完整的代码可以在 GitHub 上找到: 原型

jpa eclipselink metamodel embeddable
2个回答
6
投票

基于条件的查询可能如下所示:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Message> cq = cb.createQuery(Message.class);
Root<Message> root = cq.from(Message.class);

Predicate p = cb.conjunction();
ParameterExpression<Integer> year = cb.parameter(Integer.class, "year");
p = cb.and(p, cb.equal(root.get(Message_.stamp).get(Stamp_.year), year));

cq.where(p);

TypedQuery<Message> tq = em.createQuery(cq).setParameter("year", 2015);
List<Message> messages = tq.getResultList();

0
投票

您只需使用连续的

root
调用即可访问
get()
的嵌入属性,如本例所示:

root.get("stamp").get("year")

其中字符串常量只是相应对象中的属性名称(相应地在

Message
Stamp
中)。对于那些使用 Spring Data JPA 的人来说,这可以通过规范来表达,例如:

(root, query, criteriaBuilder) -> {
    return criteriaBuilder.lessThanOrEqualTo(root.get("stamp").get("year"), 2024)
}
© www.soinside.com 2019 - 2024. All rights reserved.