【问题标题】:Possibility to create a complexe order by with parameter通过参数创建复杂订单的可能性
【发布时间】:2021-10-29 09:28:50
【问题描述】:

在 Springboot 应用程序中,我试图首先显示带有用户固定书籍的书籍列表。我正在尝试在现有的分页规范中制作这个order by

我有书籍和用户实体,其中:

  • 一个用户可以固定多本书
  • 一本书可以由多个用户固定
@Entity
@Table(name = "book")
public class BookEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false, updatable = false)
    private Long id;

    @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
    @JoinTable(name = "user_has_book_pinned", joinColumns = @JoinColumn(name = "book_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"))
    private Set<UserEntity> userPinningBook = new HashSet<>();

}

@Entity
@Table(name = "user")
public class UserEntity implements Serializable {

    @Id
    @Column(name = "id", updatable = false, nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
    @JoinTable(name = "user_has_book_pinned", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "book_id", referencedColumnName = "id"))
    private Set<BookEntity> bookPinned = new HashSet<>();
}

尝试 1:使用 group by 和 equal

public static Specification<BookEntity> orderByPinned(long userId) {
    return new Specification<BookEntity>() {
        @Override
        public Predicate toPredicate(Root<BookEntity> root, CriteriaQuery<?> query,
                CriteriaBuilder criteriaBuilder) {
            query.distinct(true);

            Order pinnedEventOrder = criteriaBuilder.desc(criteriaBuilder.equal(root.join("userPinningBook").get("id"), userId));
            query.orderBy(pinnedEventOrder);

            return null;
        }
    };
}

其中 userId 应替换为当前用户 ID。

这里的问题是 equal 不能与这样的 order by 一起使用...

尝试 2:使用另一个带有 LEFT JOIN 的 SELECT

SELECT book.*, pinned.user_id FROM book
LEFT JOIN user_has_book_pinned pinned ON book.id = pinned.event_id AND pinned.user_id = CURRENT_USER
ORDER BY pinned.user_id DESC;

CURRENT_USER 应替换为当前用户 ID。

像这样,我们创建一个包含书籍信息和固定信息的新实体。

我需要创建一个新实体吗? 我如何将其用于图书规范?

尝试 3:使用 @Formula 和先前的选择


@Formula("(select (case WHEN count(*) > 0 THEN true ELSE false END) from book b JOIN b.userPinningBook userPinningBook where userPinningBook.book_id = id AND userPinningBook.user_id = CURRENT_USER_ID)")
private boolean isPinned;

其中 CURRENT_USER 应替换为当前用户 ID。

问题是我们不能用参数做公式,所以我不能把CURRENT_USER_ID 变成规范来得到好的顺序

有什么办法可以把固定的书放在其他书的上面吗??

【问题讨论】:

  • 您还需要置顶该书的用户列表吗?如示例所示,您选择了pinned.user_id

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


【解决方案1】:

您可以在JpaRepository&lt;BookEntity,Long&gt; 中使用如下所示的JPQL


@Query("SELECT book from BookEntity book " +
            "LEFT JOIN FETCH book.userPinningBook " +
            "WHERE book.userPinningBook.id= :id " +
            "ORDER BY book.userPinningBook.userId DESC")
List<BookEntity> findByUserPinningBookUserId(@Param("id") long id);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-01
    • 2019-06-15
    相关资源
    最近更新 更多