Spring JPA中如何实现双向匹配条件的JPQL查询(替代原生查询)
当然可以啦!你这条SQL是要查询两个用户之间的双向对话记录对吧?下面我给你几种等价的实现方式,完全符合你的需求,不用依赖原生查询:
1. 等价的JPQL语句
首先,JPQL是面向实体类的查询语言,所以要把SQL里的表名换成你的实体类名,字段名换成实体类的属性名。假设你的实体类叫Message,对应数据库里的Temp表,sender和reciever是实体类的属性,那么等价的JPQL如下:
SELECT m FROM Message m WHERE (m.sender = :sender AND m.reciever = :reciever) OR (m.sender = :reciever AND m.reciever = :sender)
这里的:sender和:reciever是命名参数,和你原SQL里的参数用法一致,只要保证参数名和后续方法里的绑定对应上就行。
2. Spring Data JPA 自定义方法实现
Spring Data JPA提供了两种方式来实现这个查询,推荐用更清晰的@Query注解方式:
方式一:@Query注解直接绑定JPQL
在你的Repository接口中定义方法,用@Query注解直接写入上面的JPQL,同时用@Param绑定参数名,这样代码可读性高,也不用写原生SQL:
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import java.util.List; public interface MessageRepository extends JpaRepository<Message, Long> { @Query("SELECT m FROM Message m WHERE (m.sender = :sender AND m.reciever = :reciever) OR (m.sender = :reciever AND m.reciever = :sender)") List<Message> findConversationBetweenUsers(@Param("sender") String sender, @Param("reciever") String reciever); }
这里方法名findConversationBetweenUsers是自定义的,只要见名知意就行,参数通过@Param和JPQL里的命名参数一一对应。
方式二:尝试Spring Data JPA命名规则(不推荐)
虽然Spring Data JPA的命名规则能实现类似逻辑,但对于这种双向OR的条件,生成的方法名会非常冗长,而且需要重复传参,可读性很差。比如:
// 注意:这种方式需要传四个参数,其中后两个是重复的sender和reciever,不推荐 List<Message> findBySenderAndRecieverOrSenderAndReciever(String sender, String reciever, String reciever2, String sender2);
调用的时候你需要传入findBySenderAndRecieverOrSenderAndReciever("A", "B", "B", "A"),显然不如@Query的方式简洁,所以更推荐用第一种方式。
注意事项
- 确保实体类名、属性名和JPQL中的名称完全一致(JPQL对大小写敏感,除非你的JPA配置了忽略大小写)
- 参数类型要和实体类属性的类型匹配(比如如果sender是Long类型,方法参数也要用Long)
- 你的Repository接口需要继承
JpaRepository或者CrudRepository才能使用Spring Data JPA的这些特性
内容的提问来源于stack exchange,提问作者Bharat Wadhwa
相关产品推荐
相关产品推荐

