如何编写多WHERE子句的JPA查询?及SQL转JPA查询求助
嘿,我来帮你搞定这两个JPA查询的问题!
编写带多个WHERE条件的JPA查询其实很直观,核心就是用AND/OR这类逻辑运算符把条件串起来,常用的实现方式有三种:
- 直接用JPQL配合@Query注解:在JPQL语句里直接写多个WHERE条件,还能结合命名参数让代码更清晰,比如:
@Query("SELECT u FROM User u WHERE u.age > :minAge AND u.status = :userStatus") List<User> findUsersByAgeAndStatus(@Param("minAge") int minAge, @Param("userStatus") String status); - Spring Data JPA衍生查询方法:如果条件不复杂,完全不用写JPQL,直接通过方法名就能自动生成查询,比如要查询年龄大于指定值且状态匹配的用户,方法名可以这么写:
List<User> findByAgeGreaterThanAndStatus(int minAge, String status); - Criteria API:适合需要动态拼接条件的场景(比如前端可选参数多,根据传入的参数决定是否添加某个WHERE条件),灵活性拉满,不过代码量会稍多一点。
先看你给出的原始SQL:
SELECT * FROM commodity comm, configuration config, customer customer where comm.commodity_id = config.commodity_id and customer.customer_id = config.customer_id and customer.customer_id=2 ;
你之前的写法有几个明显的问题:比如把实体对象直接和字段ID做比较(commodity = config.commodity_id),这肯定不对,实体对象不能直接和数据库字段值相等,得用实体的属性来对应;另外还要注意实体类名称要和你实际的Java类一致(比如你写的Customerdetails是不是应该是Customer?)。
下面给你几种正确的写法:
写法一:原生SQL查询(贴近你的原始SQL)
如果你想尽量贴近原来的SQL结构,可以用原生SQL查询,记得加上nativeQuery = true参数:
@Query(value = "SELECT comm.* FROM commodity comm, configuration config, customer customer " + "WHERE comm.commodity_id = config.commodity_id " + "AND customer.customer_id = config.customer_id " + "AND customer.customer_id = :customerId", nativeQuery = true) List<Commodity> findCommoditiesByCustomerId(@Param("customerId") Long customerId);
写法二:标准JPQL查询(推荐,符合JPA规范)
假设你的实体类映射规则是:
Commodity对应commodity表,主键属性id对应数据库的commodity_idSCConfig对应configuration表,有commodityId和customerId两个属性分别关联商品和客户的IDCustomer对应customer表,主键属性id对应数据库的customer_id
那正确的JPQL应该这么写:
@Query("SELECT comm FROM Commodity comm, SCConfig config, Customer customer " + "WHERE comm.id = config.commodityId " + "AND customer.id = config.customerId " + "AND customer.id = :customerId") List<Commodity> findCommoditiesByCustomerId(@Param("customerId") Long customerId);
更优雅的写法:利用实体关联关系
如果你的实体类之间已经定义了关联关系(比如SCConfig里用@ManyToOne关联了Commodity和Customer),那查询可以简化很多。比如SCConfig实体类是这样的:
@Entity @Table(name = "configuration") public class SCConfig { @ManyToOne @JoinColumn(name = "commodity_id") private Commodity commodity; @ManyToOne @JoinColumn(name = "customer_id") private Customer customer; // 其他字段、getter和setter }
那JPQL可以写成:
@Query("SELECT config.commodity FROM SCConfig config WHERE config.customer.id = :customerId") List<Commodity> findCommoditiesByCustomerId(@Param("customerId") Long customerId);
甚至连@Query都不用写,直接用Spring Data JPA的衍生方法:
List<Commodity> findByCustomerId(Long customerId);
(这个需要你的Spring Data JPA Repository接口定义对应上哦)
内容的提问来源于stack exchange,提问作者Prem Kumar

