PostgreSQL查询转JPA/JPQL:JOIN ON与DISTINCT实现求助
嘿,别慌!刚从原生SQL转JPA/JPQL的时候,搞不清JOIN的ON子句和DISTINCT的用法太正常了。我来帮你把这两个点掰明白,结合你的场景给出具体的写法~
一、JPQL中JOIN的ON子句怎么写?
JPQL里的JOIN分两种场景,对应不同的ON子句写法,你可以根据自己的实体关联情况选:
1. 实体之间已经定义了关联关系(比如@ManyToOne/@OneToMany)
如果你的实体类已经通过注解映射了表之间的关联(比如Product实体里有@ManyToOne private Category category;),那你可以直接利用这种关联写JOIN,默认的关联条件会由JPA自动处理,ON子句只需要加自定义的过滤条件就行:
比如原生SQL是:
SELECT c.name FROM category c JOIN product p ON c.id = p.category_id AND p.price > 100
对应的JPQL可以写成:
SELECT c.name FROM Product p JOIN p.category c ON p.price > 100 -- 只需要写自定义过滤条件,关联条件JPA自动帮你处理
2. 实体之间没有定义关联关系,手动指定关联条件
如果你的实体没有映射关联(或者需要跨无关联的表查询),那可以直接写显式JOIN并完整指定ON子句:
原生SQL:
SELECT c.name FROM category c JOIN product p ON c.id = p.category_id AND p.in_stock = true
JPQL写法:
SELECT c.name FROM Category c JOIN Product p ON c.id = p.categoryId AND p.inStock = true -- 注意这里用的是实体的属性名,不是数据库列名
二、为指定字段设置DISTINCT
JPQL里的DISTINCT用法和原生PostgreSQL几乎一致,直接放在SELECT关键字后面,作用于你指定的所有字段:
1. 单个字段去重
原生SQL:
SELECT DISTINCT c.name FROM category c JOIN product p ON c.id = p.category_id
JPQL:
SELECT DISTINCT c.name FROM Category c JOIN Product p ON c.id = p.categoryId
2. 多个字段组合去重
如果要根据多个字段的组合去重,直接把所有字段列在DISTINCT后面即可,JPA会按照字段组合来判断重复:
原生SQL:
SELECT DISTINCT c.id, c.name FROM category c JOIN product p ON c.id = p.category_id
JPQL:
SELECT DISTINCT c.id, c.name FROM Category c JOIN Product p ON c.id = p.categoryId
完整示例:结合JOIN ON和DISTINCT
假设你的原生PostgreSQL查询是:
SELECT DISTINCT c.name, c.description FROM category c JOIN product p ON c.id = p.category_id AND p.price > 50 WHERE c.active = true
对应的JPQL语句(假设Product实体有categoryId属性,或者已经映射了category关联):
SELECT DISTINCT c.name, c.description FROM Category c JOIN Product p ON c.id = p.categoryId AND p.price > 50 WHERE c.active = true
如果Product已经映射了Category关联,也可以简化成:
SELECT DISTINCT c.name, c.description FROM Product p JOIN p.category c ON p.price > 50 WHERE c.active = true
小提醒
- JPQL里用的是实体类的属性名,不是数据库表的列名,别搞混了!
- 如果用Spring Data JPA,直接把JPQL写在
@Query注解里就能绑定到Repository方法上,非常方便。
内容的提问来源于stack exchange,提问作者user5113188
相关产品推荐
相关产品推荐

