SpecificationHelper 使用注解快速构建spring-boot-starter-data-jpa查询语句

SpecificationHelper是一个辅助工具,旨在简化Spring Boot与Spring Data JPA的查询操作。通过注解@Keywords进行模糊查询,@Query进行单个属性查询,以及@QueryGroup进行分组查询,从而减少重复代码,提高开发效率。文章介绍了这三个注解的使用方法,并给出了相应的SQL示例。
摘要由CSDN通过智能技术生成

SpecificationHelper 使用注解快速构建spring-boot-starter-data-jpa查询语句

前言

  本来我是一名Android开发人员不应该写这篇文章的,但是耐不住无聊在家,然后又对这一块
比较喜欢,所以才有了这个东西,而且我前面也写过一篇关于构造一个Android RecyclerView
一个通用适配器,也不知道有没有用,唉,不废话了,还是进入我们今儿个的正题吧!
  想必大叫如果看过或者用过jpa的应该都会觉得如果查询多的话,会比较繁琐,而且每
个查询的代码又都差不多,只有条件的判断什么的有点不一样,所以从最初开始我就在网上看有没有能
减少一部分开发量的库,然而看了一圈还是没有找到比较合适的库可以使用,所以才有了今天这个工具。

目标

  这次库的目标就是减少,增加查询修改Repository的次数,在最初的时候每次有新的
需求都需要对应的去添加service和Repository的代码。废话多说,直接上代码。

使用方式

1、模糊查询 @Keywords

  先来看看Keywords的注解吧

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Keywords {
   

    /**
     * 需要查询的字段名,在Specification中称为path(路径)
     * @return
     */
    String[] value();

    /**
     * @see QueryGroup
     * 该查询的名称,方便我们后面QueryGroup做分组查询
     * @return
     */
    String name() default "";

    /**
     * 模糊查询的前缀,默认为 %
     * @return
     */
    String prefix() default "%";

    /**
     * 模糊查询的后缀,默认为 %
     * @return
     */
    String suffix() default "%";

    /**
     * @see Operator
     * 模糊查询连接条件 分为 AND 和 OR
     * @return
     */
    Operator operator() default Operator.OR;
}

  查询条件代码

@Data
public static class KeywordsQueryCriteria implements Serializable {
   

    /**
     * 模糊查询 account 和 token 两个字段,连接条件为 OR
     */
    @Keywords(value = {
   "account", "token"}, suffix = "%", prefix = "%", operator = Operator.OR)
    private String keywords;

}

  查询生成的sql

SELECT
	accountent0_.id AS id1_0_,
	accountent0_.create_time AS create_t2_0_,
	accountent0_.is_delete AS is_delet3_0_,
	accountent0_.delete_time AS delete_t4_0_,
	accountent0_.update_time AS update_t5_0_,
	accountent0_.account AS account6_0_,
	accountent0_.ENABLE AS enable7_0_,
	accountent0_.locked AS locked8_0_,
	accountent0_.register_ip AS register9_0_,
	accountent0_.token AS token10_0_,
	accountent0_.type AS type11_0_ 
FROM
	tk_account accountent0_ 
WHERE
	accountent0_.account LIKE ? 
	OR accountent0_.token LIKE ?

  看这样子是我们想要的结果,

2、单条属性查询 @Query

  注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(value = Queries.class)
public @interface Query {
   

    /**
     * @see QueryType
     * 查询类型
     * NOT_EQUAL 不相等
     * EQUAL 相等
     * GREATER_THAN 大于
     * GREATER_THAN_OR_EQUAL 大于等于
     * LESS_THAN 小于
     * LESS_THAN_OR_EQUAL 小于等于
     * IN 在集合或数组内 必须注解在 array 或者 Collection上
     * BETWEEN 在范围内 必须注解在 array 或者 List 上,并且元素要大于或等于2
     * @return
     */

    QueryType type();

    /**
     * @see QueryGroup
     * 该查询名称,方便我们后面QueryGroup做分组查询
     * @return 默认使用属性名
     */
    String name() default "";

    /**
     * 查询字段 path
     * @return 优先使用配置的路径,然后使用名称,最后使用属性名
     */
    String path() default "";
}

  使用,这儿有一个需要特别注意的地方,就是两个token的查询,需要给其中一个取名,不然会只有查询其中 一个

@Data
public static class QueryCriteria implements Serializable {
   

    /**
     * 查询范围内的id,这儿例子给的是0-20
     */
    @Query(type = QueryType.BETWEEN, path = "id")
    private Integer[] ids;

    /**
     * 查询在集合内的账号,这儿给的粒子是["123", "456", "789"]
     */
    @Query(type = QueryType.IN, path = "account")
    private String[] accounts;

    /**
     * 模糊查询token,给其查询取名为keyword_token,如果不取名默认为属性名和下面的查询冲突了
     */
    @Keywords(value = "token", name = "keyword_token")
    /**
     * 查询不为null的token,虽然没有实际意义,这儿只是给个例子,说明可以多次查同一字段
     */
    @Query(type = QueryType.IS_NULL, path = "token")
    private String token;

    /**
     * 查询delete条件
     */
    @Query(type = QueryType.EQUAL)
    private Boolean delete;
}

  查询生成的sql

SELECT
	accountent0_.id AS id1_0_,
	accountent0_.create_time AS create_t2_0_,
	accountent0_.is_delete AS is_delet3_0_,
	accountent0_.delete_time AS delete_t4_0_,
	accountent0_.update_time AS update_t5_0_,
	accountent0_.account AS account6_0_,
	accountent0_.ENABLE AS enable7_0_,
	accountent0_.locked AS locked8_0_,
	accountent0_.register_ip AS register9_0_,
	accountent0_.token AS token10_0_,
	accountent0_.type AS type11_0_ 
FROM
	tk_account accountent0_ 
WHERE
	( accountent0_.token IS NULL ) 
	AND (
	accountent0_.token LIKE ?) 
	AND ( accountent0_.id BETWEEN 0 AND 20 ) 
	AND accountent0_.is_delete =?

  查询使用的json

{
   
    "ids":[0,20],
    "accounts":["123", "456", "789"],
    "token": "123",
    "delete": true
}

  大家看到这儿是不是总觉得还差些什么?生成的sql,总是不能完全满足自己的要求,而且还不能控制多个查询之间的关系。
对,觉得差就对了,我们还差一个分组查询,能够任意组合我们几个查询之间关系的这么个东西,所以下面就出来了。

3、真正厉害的查询 @QueryGroup 分组查询(不是sql中 groupBy 查询,是把其中几个查询添加合并为一个)

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(QueryGroups.class)
public @interface QueryGroup {
   

    /**
     * 查询名称 可以把几个查询合并为一个查询,然后在用于其他的组
     * @return
     */
    String name();

    /**
     * 查询的目标名称
     * @return
     */
    String[] targetNames() default {
   };

    /**
     * 分组查询的条件 OR 或 AND
     * @return
     */
    Operator operator() default Operator.AND;

}

@Data
@QueryGroup(name 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值