SpringBoot JPA实践之@Query查询之动态查询条件

JPA
placeholder image
admin 发布于:2020-05-01 22:06:38
阅读:loading

通过前面一篇文章介绍了查询时传递参数的3种方式,包含了对于@Query注解查询的基本使用,如参数等值查询、参数模糊查询、及参数集合 in 的查询方式,然而实际应用中绝不会都是这么简单的查询,往往伴随的是参数动态查询,即当参数值为空时不使用该参数,通常包含场景是单个参数的匹配与数组结构的参数匹配,详细实现如下。

代码实现

Repository

/**
 * 
根据参数构造动态查询条件
 
*
 * @author chendd
 * @date 2020/5/1 23:44
 */
public interface UserQueryDynamicParamRepository extends BaseRepository<User , String> {

    
/**
     * 
常规动态参数实现:出现多少次 则需要定义多少个方法参数
     
*/
    
@Query(value = "select a.* from user a where 1=1 " +
            
"and (? is null or a.name = ?) " +
            
"and (? is null or a.email = ?) " , nativeQuery = true)
    List<User> queryUsersByNameAndEmailGeneral(String nameFlag , String name ,
                                               String emailFlag , String email);

    
/**
     * 
常规动态参数实现:使用 ?数字 的参数类型
     
*/
    
@Query(value = "select a.* from user a where 1=1 " +
            
"and (?1 is null or a.name = ?1) " +
            
"and (?2 is null or a.email = ?2) " , nativeQuery = true)
    List<User> queryUsersByNameAndEmailGeneral(String name , String email);

    
/**
     * 
涉及 in 条件的动态查询
     
*/
    
@Query(value = "select a.* from user a where 1=1 " +
            
"and if(?1 is not null , a.name = ?1 , 1=1) " +
            
"and if(?2 is not null , a.email in (?3) , 1=1) " , nativeQuery = true)
    List<User> queryUsersByNameAndEmailList(String name , String emailValue , List<String> emails);

    
/**
     * 
涉及 in 条件的动态查询
     
*/
    
@Query(value = "select a.* from user a where 1=1 " +
            
"and if(:name is not null , a.name = :name , 1=1) " +
            
"and if(:emailValue is not null , a.email in (:emails) , 1=1) " , nativeQuery = true)
    List<User> queryUsersByNameAndEmailArray(
@Param("name") String name ,
                                             
@Param("emailValue") String emailValue ,
                                             
@Param("emails") String[] emails);

}

Test

  /**

  * 测试动态查询条件
 
*
 * @author chendd
 * @date 2020/5/1 23:47
 */
public class UserQueryDynamicParamTest extends ApplicationTest {

   
@Resource
   
private UserQueryDynamicParamRepository repository;

   
@Test
   
public void testQueryDynamicParamGeneral4() {
        List<User> userList =
repository.queryUsersByNameAndEmailGeneral(
               
"chendd" , "chendd" , "8866" , "8866");
        Assert.assertNotNull(userList);
    }

   
@Test
   
public void testQueryDynamicParamGeneral2() {
        List<User> userList =
repository.queryUsersByNameAndEmailGeneral(
               
"chendd" , "8866");
        System.
out.println(userList);
        Assert.assertNotNull(userList);
    }

   
@Test
   
public void testQueryDynamicParamList() {
        List<String> emailList = Lists.newArrayList(
"8877" , "8888");
        List<User> userList =
repository.queryUsersByNameAndEmailList(
               
"chendd" , CollectionUtils.isEmpty(emailList) ? null : "notNull" , emailList);
        Assert.assertNotNull(userList);
    }

   
@Test
   
public void testQueryDynamicParamArray() {
        String emailArray[] = {
"8866" , "8888"};
        List<User> userList =
repository.queryUsersByNameAndEmailArray(
               
"chendd" , ArrayUtils.isEmpty(emailArray) ? null : "notNull" , emailArray);
        Assert.assertNotNull(userList);
    }

}

实现分解

(1)方法queryUsersByNameAndEmailGeneral(4个参数)是最常见的动态参数实现,最容易理解也是最鸡肋的,本来要实现2个字段的参数查询,但函数确定义了4个参数,且连续两个奇偶都是同一个参数的重复值; 

(2)方法queryUsersByNameAndEmailGeneral(2个参数)是上述实现的升级版本,使用起来简单明了,为两个参数的等值匹配,当参数不为空时按传递参数进行查询;

(3)方法queryUsersByNameAndEmailList是稍微复杂点的查询实现,同样包含了两个参数的动态查询,但是其中一个为 in 查询,由于 in 的查询为多个,所以在有需要查询 in 条件的时候首先排除该实现“方法queryUsersByNameAndEmailGeneral(4个参数)”使用其它方式实现,由于此处的?3的参数为集合数组类型,故在具体应用中底层配解析成了多个 ? ,而用于判断该参数是否为空时就需要依赖一个标记类的变量,当传递的集合数组为空时我们传递对应的null,否则传递任意一个不为null的参数,使其执行非空逻辑的SQL条件即可;

(4)queryUsersByNameAndEmailArray的实现与queryUsersByNameAndEmailList一致,只是演示可以传递List或String[]等结构参数,具体传递何种类型需要自行选择;

(5)注意上述Repository中含if函数的实现是MySQL数据库支持的动态查询条件的方式,类似Oracle的实现无法使用;


 点赞


 发表评论

当前回复:作者

 评论列表


留言区