如何生成具有外键属性的通用CriteriaQuery?

时间:2018-12-04 13:59:09

标签: java jpa criteria-api

实体示例:

@Entity
public class Employee {
    @Id
    @Column(name="EMP_ID")
    private long id;
    ...
    @OneToMany(mappedBy="owner")
    private List<Phone> phones;
    ...
}
@Entity
public class Phone {
    @Id
    private long id;    
    ...
    @ManyToOne
    @JoinColumn(name="OWNER_ID")
    private Employee owner;
    ...
}

我有一个通用类,其中根据实体的类型生成查询:

public class Repository<T>
{
    private Class<T> type;

    public List<T> select(String property, Object value) {
        EntityManager em = getEntityManager();
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<T> q = cb.createQuery(type);
        Root<T> root = q.from(type);
        Path<Object> path = root.get(property);
        query.where(path.in(value));
        query.select(q.select(root));
        TypedQuery<A> query = em.createQuery(q);
        return query.getResultList();
    }
}

我要生成以下查询

SELECT * FROM PHONE WHERE OWNER_ID = ?

执行

Repository<Phone> repository;
List<Phone> phones = repository.select("owner.id", 1);

但是它不起作用,因为找不到“ owner.id”。尽管声明

em.createQuery("SELECT p FROM Phone p WHERE p.owner.id = :id")

实际上正在工作。

如何在不知道T类型的情况下基于类型Employee创建通用CriteriaQuery并导致指定的语句?

2 个答案:

答案 0 :(得分:1)

您必须拆分property,然后加入Employee。对于一级连接,它可能看起来像这样:

 String[] splitProperty = property.split(".");
 Join<Object, Object> owner = root.join(splitProperty[0]);
 Path<Object> path = owner.get(splitProperty[1]);
 q.where(path.in(value));
 ...

当然,如果要使用更通用的解决方案,则必须遍历拆分的部分并加入其他表。

答案 1 :(得分:1)

您可以从子实体(@model MyApp.ImageModel <img src="@Model.ImageSrc" class="img-responsive" alt="" /> )加入父级(Employee),并向被加入实体询问其Phone属性。

id