jpa - Criteria API 连接问题:不包含关系列的实体不能“连接”
问题描述
所需的实体大致如下:
@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 ...
}
这是与中间表的多对多关系:
组 <----- 1:N -----> GroupMember <----- N:1 -----> 用户
我想要实现的查询(通过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
的实体如何与其他实体?
解决方案
基于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
推荐阅读
- php - WooCommerce:当特定产品在购物车中时更改税率
- ms-access - MS Access DLookup 文本字段语法问题
- flutter - Flutter:如何将焦点转移到下一个 TextFormField?
- java - 错误“线程“AWT-EventQueue-0”中的异常 java.lang.NumberFormatException:对于输入字符串:“”” java Netbeans
- csv - 使用 HTTP 源读取 CSV 导出时 Cloud Data Fusion 出现问题
- reactjs - Axios 取消令牌不起作用。我该如何解决?
- javascript - jQuery.Deferred 异常:未定义数据 - ReferenceError
- javascript - 使用 React Router 防止组件安装在每个渲染上
- assembly - 似乎无法识别 8085 程序集中的 JNC 语句中的错误
- bash - 使用 bash 脚本,如何连接文本以重命名文件?