【发布时间】: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