如何使用外键 属性 生成通用 CriteriaQuery?
How to generate a generic CriteriaQuery with foreign key property?
示例实体:
@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;
...
}
我有一个通用的 class,其中根据实体类型生成查询:
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")
确实有效。
如何在不知道 Employee
类型的情况下创建基于类型 T
的通用 CriteriaQuery,从而生成指定的语句?
您必须拆分您的 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));
...
当然,如果您想要更通用的解决方案,则必须遍历拆分部分并加入其他表。
您可以从子实体 (Phone
) 加入到父实体 (Employee
) 并向已加入的实体请求其 id
属性.
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Child> cq = cb.createQuery(Child.class);
Root<Child> cr = cq.from(Child.class);
Join<Child, Parent> pj = cr.join("parent");
cq.where(cb.equal(pj.get("id"), 1));
List<Child> rl = em.createQuery(cq).getResultList();
System.out.println(rl);
示例实体:
@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;
...
}
我有一个通用的 class,其中根据实体类型生成查询:
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")
确实有效。
如何在不知道 Employee
类型的情况下创建基于类型 T
的通用 CriteriaQuery,从而生成指定的语句?
您必须拆分您的 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));
...
当然,如果您想要更通用的解决方案,则必须遍历拆分部分并加入其他表。
您可以从子实体 (Phone
) 加入到父实体 (Employee
) 并向已加入的实体请求其 id
属性.
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Child> cq = cb.createQuery(Child.class);
Root<Child> cr = cq.from(Child.class);
Join<Child, Parent> pj = cr.join("parent");
cq.where(cb.equal(pj.get("id"), 1));
List<Child> rl = em.createQuery(cq).getResultList();
System.out.println(rl);