order by a field in a filtered OneToMany relation using JPA Specification ( CriteriaQuery CriteriaBuilder )

huangapple go评论69阅读模式
英文:

order by a field in a filtered OneToMany relation using JPA Specification ( CriteriaQuery CriteriaBuilder )

问题

What I want to achieve : 在应用条件后,对 @OneToMany 关系中的 Book 实体列表进行排序,具体排序属性是 order

@Entity
public class Book {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "bookId")
  private Long id;

  @OneToMany(mappedBy = "entity", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
  Set<RowOrder> orders;
}
@Entity
public class RowOrder {

  @EmbeddedId
  private RowOrderId id;

  @ManyToOne
  @MapsId("entityId")
  @JoinColumn(name = "entity_id")
  private Book entity; 

  @ManyToOne
  @MapsId("userId")
  @JoinColumn(name = "user_id")
  private User user;

  @Column(name = "entity_order")
  private Long order;
}
@Entity
public class User {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "userId")
  private Long id;
}

我想要按照 order.userId == aUser.id 来对 books 进行排序。

我使用 jpa.domain.Specification 进行过滤,我希望在这个过滤条件下应用排序。

@AllArgsConstructor
public class BookSpecification implements Specification<Book> {

  ...

  @Override
  public Predicate toPredicate(Root<Task> root, CriteriaQuery<?> criteriaQuery,
      CriteriaBuilder criteriaBuilder) {

 ...

aUser ; // 这是我希望应用于关系的用户实体

criteriaQuery.orderBy(criteriaBuilder.asc(
        root.join("orders", JoinType.LEFT) // <--- 如何在这里筛选,WHERE row_order.user_id = aUser.id
            .get("order")) 
    );

   ...
}
  • 我该如何实现这个目标?
  • 在使用 CriteriaBuilder 时,我能否编写一些原生 SQL?如果可以,我如何编写我的情况下的 OrderBy 语句,使用原生 SQL?
英文:

What I want to achieve : order a list of Book entities on a @OneToMany relation, on a specific attribute after applying a condition.

@Entity
public class Book{

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = &quot;bookId&quot;)
  private Long id;

  @OneToMany(mappedBy = &quot;entity&quot;, cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
      Set&lt;RowOrder&gt; orders;
}

@Entity
public class RowOrder {

  @EmbeddedId
  private RowOrderId id;

  @ManyToOne
  @MapsId(&quot;entityId&quot;)
  @JoinColumn(name = &quot;entity_id&quot;)
  private Book entity; 

  @ManyToOne
  @MapsId(&quot;userId&quot;)
  @JoinColumn(name = &quot;user_id&quot;)
  private User user;

  @Column(name = &quot;entity_order&quot;)
  private Long order;
}
@Entity
public class User {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = &quot;userId&quot;)
  private Long id;
}

I want to order books by book.orders.order in which order.userId == aUser.id.

I am using jpa.domain.Specification to filter in which I want to apply this order.



@AllArgsConstructor
public class BookSpecification implements Specification&lt;Book&gt; {

  ...

  @Override
  public Predicate toPredicate(Root&lt;Task&gt; root, CriteriaQuery&lt;?&gt; criteriaQuery,
      CriteriaBuilder criteriaBuilder) {

 ...

aUser ; // this the user entity in which i want to apply on the relation

 criteriaQuery.orderBy(criteriaBuilder.asc(
        root.join(&quot;orders&quot;, JoinType.LEFT) // &lt;--- how to filter this with, WHERE row_order.user_id = aUser.id
            .get(&quot;order&quot;)) 
    );

   ...
}
  • how can I achieve this ?
  • can I write some native sql when using CriteriaBuilder? if so how can I write the OrderBy cause in my case with a natvie sql ?

答案1

得分: 0

这是我们的解决方法:

      Join<Book, RowOrder> books_orders_join = root.join("orders", JoinType.LEFT);
      Join<Join<Book, RowOrder>, User> books_orders_users_join = books_orders_join
          .join("user", JoinType.LEFT);

      predicates
          .add(
              criteriaBuilder
                  .equal(books_orders_users_join.get("id"), aUser.getId()));

      criteriaQuery.orderBy(criteriaBuilder.asc(books_orders_join.get("order")));
英文:

this how we solved it:

      Join&lt;Book, RowOrder&gt; books_orders_join = root.join(&quot;orders&quot;, JoinType.LEFT);
      Join&lt;Join&lt;Book, RowOrder&gt;, User&gt; books_orders_users_join = books_orders_join
          .join(&quot;user&quot;, JoinType.LEFT);

      predicates
          .add(
              criteriaBuilder
                  .equal(books_orders_users_join.get(&quot;id&quot;), aUser.getId()));

      criteriaQuery.orderBy(criteriaBuilder.asc(books_orders_join.get(&quot;order&quot;)));

huangapple
  • 本文由 发表于 2020年4月6日 14:11:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/61053893.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定