【问题标题】:Criteria API join problem: entity which does not hold relationship column can not "join"Criteria API 连接问题:不包含关系列的实体不能“连接”
【发布时间】:2020-05-11 12:15:46
【问题描述】:

所需的实体大致如下:

@Entity
@Table(name = "tb_users")
public class User {

    @Id
    @GeneratedValue
    private UUID userId;

    // Omitted other fields and getters/setters ...
}
@Entity
@Table(name = "tb_groups")
public class Group {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer groupId;

    // ....
}
@Entity
@Table(name = "tb_group_members")
public class GroupMember {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "group_id")
    private Group group;

    // getters & setters ...
}

这是与中间表的多对多关系:

组 GroupMember 用户

我要实现的查询(通过Criteria API)与下面的JPQL基本相同:

select g from Group g join GroupMember gm on g = gm.group where gm.user = ? and  ...or whatever...

我尝试按如下方式构造 CriteriaQuery:

User userToQuery = ...;
// ....
CriteriaQuery<Group> query = criteriaBuilder.createQuery(Group.class);
Root<Group> groupRoot = query.from(Group.class);
Root<GroupMember> gmRoot = query.from(GroupMember.class);
groupRoot.join(...).on(criteriaBuilder.equal(groupRoot, gmRoot.get("group"))); // I can't find a suitable join() method to specify the relationship
Predicate predicate = criteriaBuilder.equal(gmRoot.get("user"), userToQuery);
// ......

由于Group实体没有关联关系,所以不知道怎么调用join(...)方法。

我必须反向声明关联,即从 GroupMember 实体:

CriteriaQuery<GroupMember> query = criteriaBuilder.createQuery(GroupMember.class);
Root<GroupMember> gmRoot = query.from(GroupMember.class);
gmRoot.join("group");
// ......

JPA 的 Criteria API 有这个限制吗? 不包含关联字段join的实体如何与其他实体?

【问题讨论】:

  • 您的 JPQL 有效吗?你试过像SELECT gm.group FROM GroupMember gm WHERE gm.user=:user这样的JPQL吗?我认为,如果它确实有效,则更容易转换为标准 API。
  • 这能回答你的问题吗? JPA - left join 2 tables without association
  • 非常感谢~ Jens & Nikos!答案直接使用 JPQL,我已经给出了我的 JPQL,它工作正常。我希望使用Creteria API来解决这个问题,因为这样可以解决concat查询参数的问题
  • 我已经放弃使用 Creteria API。我将尝试使用 Querydsl 进行更灵活的查询。

标签: jpa spring-data-jpa criteria-api


【解决方案1】:

基于Querydsl的实现:

private EntityManager em;

......

User user = ...; // User to query (may be null)
...
QGroup qGroup = QGroup.group;
QGroupMemeber qGMember = QGroupMember.groupMember;

JPAQueryFactory queryFactory = new JPAQueryFactory(em);
JPAQuery<Group> query = (user == null) ?
        queryFactory.selectFrom(qGroup) :
        queryFactory.select(qGroup).from(qGroup).join(qGMember).on(qGroup.eq(qGMember.group));

BooleanBuilder builder = new BooleanBuilder();
if (user != null) {
    builder.and(qGMember.user.eq(user));
}
// if (...) {
//     Other conditions that need to be added to the where clause
// }
query.where(builder);
// Paging condition or something
// ....

List<Group> result = query.fetch(); // search result

【讨论】:

    猜你喜欢
    • 2013-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-11
    • 2013-03-31
    • 2011-05-16
    • 2012-04-09
    相关资源
    最近更新 更多