gpt4 book ai didi

jpa - JPA 标准 API 和多个子查询的问题

转载 作者:行者123 更新时间:2023-12-02 04:45:48 25 4
gpt4 key购买 nike

我正在努力使用 JPA Criteria API 来为我的数据结构制定查询。好的,我的实体如下。我有用户和组(两者共享一个公共(public)基类 OrgEntity)。从逻辑上讲,用户当然可以是多个组的成员。最后,我有一个代表任务的实体,它有一个潜在所有者列表(可以是单个用户或整个组)。域模型总结如下并给出,因此我无法更改它。

@Entity
@Inheritance(strategy=InheritanceType.JOINED)
abstract public class OrgEntity {
@Id
public String name;
...
}

@Entity
public class User extends OrgEntity {
public String displayName;

@ManyToMany(mappedBy="members")
public List<Group> groups;
...
}

@Entity
public class Group extends OrgEntity {
@ManyToMany
public List<User> members;
...
}

@Entity
public class Task {
@Id
public String uuid;

@ManyToMany
public List<OrgEntity> potentialOwners;

...
}

我查询的起点是 User 的单个实例。我想知道用户是潜在所有者的所有任务(无论用户是直接包含在 potentialOwners 集合中还是包含在 potentialOwners 中的组的成员)。

我第一次使用命名查询的尝试如下

SELECT DISTINCT t FROM Task AS t JOIN t.potentialOwners po 
WHERE (po IN (SELECT g FROM User u JOIN u.groups g WHERE u = :user)
OR po IN (SELECT u FROM User u WHERE u = :user))

它有效,但我不知道这是否是最有效的方法。有什么建议吗?

但是,我不知道如何使用标准 API 来实现它。有人可以帮我解决这个问题吗?

谢谢

最佳答案

好吧,我终于知道怎么做了。如果您对我的解决方案感兴趣,请看这里。 u 是用户对象,基本上是查询参数,em 是 EntityManager 实例。

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();

// specifies the result value of the query
CriteriaQuery<Task> cq = criteriaBuilder.createQuery(Task.class);
// start with the navigation at the task entity
Root<Task> from = cq.from(Task.class);
// join the potential owner organizational entities
Join<Task,OrgEntity> potentialOwners = from.join("potentialOwners");
// select the tasks but remove duplicates
CriteriaQuery<Task> select = cq.select(from).distinct(true);

// definition for subquery1: fetch the user instance
Subquery<User> subquery1 = cq.subquery(User.class);
// start at the User entities
Root<User> from1 = subquery1.from(User.class);
// select the whole user
subquery1.select(from1);
// based on the specified user
subquery1.where(criteriaBuilder.equal(from1, u));

// definition for subquery2: fetch all groups for given user
Subquery<Group> subquery2 = cq.subquery(Group.class);
// we start at the User entity
Root<User> from2 = subquery2.from(User.class);
// join to Group entities via the groups collection
Join<User, Group> groups = from2.join("groups");
// select the group entities only
subquery2.select(groups).distinct(true);
// and finally restrict to all groups of the specified user
subquery2.where(criteriaBuilder.equal(from2, u));

// order in descending order based on the unique task id
select.orderBy(criteriaBuilder.desc(from.get("uuid")));

// here we restrict to those tasks that have the potential
// owners either in the result set of subquery2 or subquery1
// additionally I've tried to filter for another restriction
// in the task (based on a like statement of the uuid)
select.where(criteriaBuilder.and(
criteriaBuilder.or(
criteriaBuilder.in(potentialOwners).value(subquery2),
criteriaBuilder.in(potentialOwners).value(subquery1)),
criteriaBuilder.like(from.<String>get("uuid"), "1%")));


TypedQuery<Task> typedQuery = em.createQuery(select);
List<Task> resultList = typedQuery.getResultList();

关于jpa - JPA 标准 API 和多个子查询的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19814910/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com