如何在JPA中查询去重后的记录(忽略主键差异)?
解决方案
为啥原来的方法不管用?
findByName本来就会返回所有匹配name的记录,而findDistinctByName的distinct是看整个实体对象的唯一性——因为id是主键,id=1和id=3的记录虽然name、tech都一样,但id不同,所以JPA会把它们当成不同的实体,自然返回全部3条。
怎么实现需求?
要拿到每个name对应的唯一一条记录(这里是id最小的那条,也就是你要的id=1和2),可以用下面几种JPA查询方式:
1. JPQL跨库写法(推荐)
在你的Repository接口里加这个方法:
@Query("SELECT e FROM Employee e WHERE e.id IN (SELECT MIN(e2.id) FROM Employee e2 GROUP BY e2.name)") List<Employee> findUniqueByNameWithMinId();
- 逻辑很简单:先按name分组,找出每组里id最小的那条的id,再用这些id去查完整记录,这样每个name就只会返回一条最早的记录。
2. PostgreSQL原生SQL写法
如果你习惯用数据库原生语法,也可以这么写:
@Query(value = "SELECT * FROM your_table e WHERE e.id IN (SELECT MIN(id) FROM your_table GROUP BY name)", nativeQuery = true) List<Employee> findUniqueByNameWithMinIdNative();
- 记得把
your_table换成你实际的表名。
3. 关联分组的JPQL写法
还有另一种JPQL思路,通过子查询关联来取数:
@Query("SELECT e FROM Employee e JOIN (SELECT MIN(id) as minId, name FROM Employee GROUP BY name) e2 ON e.id = e2.minId") List<Employee> findUniqueByName();
额外说明
要是你的需求不是取id最小的,而是其他规则(比如要最新创建的记录),只要把子查询里的MIN(id)换成对应的聚合条件就行,比如MAX(create_time),再调整关联字段就好。
内容的提问来源于stack exchange,提问作者tiya
相关产品推荐
相关产品推荐

