【问题标题】:Self join in criteria query条件查询中的自联接
【发布时间】:2018-08-21 13:25:11
【问题描述】:

所以我有一个名为“用户”的表,其字段为

  • 用户ID
  • 用户名
  • supervisorId

我想获取特定用户的主管的用户名。

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);
Root<User> rootUser = criteriaQuery.from(User.class);
List<Predicate> predList = new ArrayList<Predicate>();
Join<User, User> selfJoin = rootUser.join("userId", JoinType.LEFT); //not sure about this line
predList.add(criteriaBuilder.equal(selfJoin.<String>get("userId"), supervisorId)); //supervisorId is the id of the supervisor that I want to find
TypedQuery<User> typedQuery = em.createQuery(criteriaQuery);
List<User> resultList = typedQuery.getResultList();

现在除了这个 supervisorId,我还有很多其他条件。所以我必须使用相同的条件查询。

谢谢。

【问题讨论】:

    标签: java jpa orm criteria-api self-join


    【解决方案1】:

    Criteria API 适用于您需要build queries dynamically 时,您应该始终记住它是基于遍历实体的。

    您需要的是这样的普通 SQL 查询:

    select sp.userName
    from users u
    join users sp on sp.userId = u.supervisorId
    where userId = ?
    

    仅仅因为您使用 JPA 和 Hibernate,it does not mean that you should not use SQL queries

    如果您map the supervisor as a @ManyToOne association,则可以相当容易地编写 Criteria API 查询:

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="supervisorId", referencedColumnName="userId")
    private User supervisor;
    

    那么,join就变成了:

    Join<User, User> selfJoin = rootUser.join("supervisor", JoinType.LEFT);
    

    【讨论】:

      【解决方案2】:

      我实施并为我工作的示例。这不是一个确切的代码,但这个应该可以工作。我没有在同一个实体中创建引用变量。

      SQL

      select right.* from MyTable left, MyTable right where left.subjectid = 7 and left.studentid = right.studentid
      and left.subjectid != right.subjectid;
      

      标准代码

      CriteriaBuilder builder = entityManager.getCriteriaBuilder();
      CriteriaQuery<MyTable]> criteria = builder.createQuery(MyTable.class);
      Root<MyTable> MyTableRootLeft = criteria.from(MyTable.class);
      Root<MyTable> MyTableRootRight = criteria.from(MyTable.class);
      Predicate selfJoinPredicate = 
      builder.and(
                  builder.equal(MyTableRootLeft.get(subjectid), subjectid),
                  builder.equal(MyTableRootLeft.get(studentid),MyTableRootRight.get(studentid)),
                    builder.notEqual(MyTableRootLeft.get(subjectid),
      MyTableRootRight.get(subjectid)));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多