java jpa set_java – JPA:如何对实体中的Set字段进行排序?

我使用的是Spring 3.2.11.RELEASE,Hibernate 4.3.6.Final和JPA 2.1.我有以下实体与以下字段…

@Entity

@Table(name = "user")

public class User implements Serializable, Comparable

{

@ManyToMany

@JoinTable(name = "user_organization", joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "ORGANIZATION_ID") })

@LazyCollection(LazyCollectionOption.FALSE)

@SortNatural

private SortedSet organizations;

上面,组织的排序由组织的名称字段完成.当我运行JPA查询来检索User对象时,我想根据与之关联的组织的有序列表进行排序.我试过这个……

final CriteriaBuilder builder = m_entityManager.getCriteriaBuilder();

final CriteriaQuery criteria = builder.createQuery(User.class);

final SetJoin orgsJoin = orderByRoot.join(User_.organizations, JoinType.LEFT);

orderByExpr = orgsJoin.get(Organization_.name);

criteria.orderBy(builder.asc(orderByExpr);

但它不适用于用户与多个组织相关联的情况 – 有时在其列表中按字母顺序排列较低的组织的用户将在正确的用户之前返回.如果不编写一大堆原生SQL,我怎么能用JPA / CriteriaBuilder解决这个问题?

编辑:这是我想要的一个例子.我正在寻找不同的用户.

>用户A有组织,“AAA大楼”和“ZZZ大楼”

>用户B只有“MMM大楼”的组织

>用户C组织“CCC Building”和“VVV Buidling”

>用户D组织“AAA Building”和“MMM Buidling”

我想要用户D,用户A,用户C和用户B,因为用户A的组织的串联按字母顺序低于用户C的组织的串联,这些组织的字母顺序低于用户B的组织.

解决方法:

您无法为实体编写此类查询.如果您使用的是原生SQL,那么user.id可以组织GROUP BY组织名称,但这不是您想要的.

您只需获取加入用户和组织:

final CriteriaBuilder builder = m_entityManager.getCriteriaBuilder();

final CriteriaQuery criteria = builder.createQuery(User.class);

Root root = criteria.from(User.class);

Fetch organizations = root.fetch("organizations");

criteria.select(c);

TypedQuery query = em.createQuery(criteria);

List users = query.getResultList();

并在内存中对它们进行排序:

Collections.sort(users, new Comparator() {

@Override

public int compare(User user1, User user2) {

SortedSet organizations1 = user1.getOrganizations();

SortedSet organizations2 = user2.getOrganizations();

if(organizations1.isEmpty()) {

if(organizations2.isEmpty()) {

return 0;

} else {

return -1;

}

} else {

if(organizations2.isEmpty()) {

return 1;

} else {

Organization o1 = organizations1.first();

Organization o2 = organizations2.first();

return o1.compareTo(o2);

}

}

}

});

更新

如果您不想在内存中获取所有内容以进行排序,那么我认为仅使用JPQL或Criteria API是不可能的.

假设组织名称是VARCHAR(50),我们首先需要使用正确的填充,然后我们需要首先运行group_concat本机查询:

PostgrSql

SELECT o.user_id,

string_agg(RPAD(o.name, 50) ORDER BY o.name) as ordr

FROM Organization o

GROUP BY o.user_id

order by ordr

MySQL的

SELECT o.user_id,

group_concat(RPAD(o.name, 50) ORDER BY o.name) as ordr

FROM Organization o

GROUP BY o.user_id

order by ordr

对user_id进行排序后,您只需将user_ids提取到List< Long>即可.然后运行第二个JPQL查询来获取用户:

List userIds = ...;

TypedQuery q = em.createQuery(

"select u " +

"from User u " +

"where u.id in :userIds "

, User.class);

q.setParameter("userIds", userIds);

List users = q.getResultList();

标签:java,sorting,orm,jpa,hibernate

来源: https://codeday.me/bug/20190609/1206291.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值