背景
jpa 是使用非常广泛的orm框架,开发也非常方便,但是我觉得jpa的Query注解有两个不友好的地方:
-
使用Query注解编写SQL/HQL时,参数不能动态设置
MyBatis 有这种标签来动态控制参数,而jpa没有,事实上很多业务场景都需要动态控制参数,jpa 遇到这种场景,一般有这几种方式实现: - 使用 EntityManager.createNativeQuery,动态拼接SQL,如下案例:
- 使用 QueryByExampleExecutor(QBE)方式,类似如下:
- 使用 JpaSpecificationExecutor 方式,类似如下:
- @Query 动态参数方式,如下:
@Query("select u.name as name,u.email as email from User u where (:name is null or u.name =:name) and (:email is null or u.email =:email)")
UserOnlyName findByUser(@Param("name") String name,@Param("email") String email);
第一种方式需要自己拼接原生SQL,如果是分页情况,还需要写获取总数等相关SQL,使用比较麻烦;
第二种和第三种都是自己拼接出需要的参数,分页可以不需要特别处理,但是只能单表操作,不能做join;
第四种虽然解决了动态SQL问题,但是写的SQL不够友好,而且也会影响性能(可能索引会失效);
使用Query注解返回VO对象,需要利用 JPQL,new 了一个 利用 JPQL,new 了一个 VO对象,再通过构造方法,接收查询结果(或者用接口去接收)如下图:
针对以上的两点,我就想自己扩展jpa框架,对jpa做一个增强。
增强的功能
动态参数支持以下写法:
1. 占位符position解析方式
如上图,对于需要动态传参的参数使用占位符 ?{}
包裹起来,参数可以使用 ?1 等占位符;
2. 占位符name参数名解析方式
如上图所示,对于需要动态传参的参数仍然使用占位符 ?{}
包裹起来,但是参数可以使用 :name 方式占位,不过注意的是,参数名需要使用 @RequestParam 标注;
3. 非占位符position解析方式
如果你不想写 ?{}
占位符,也可以去掉,但是这种只支持如上图一样简单的条件,目前支持是类似如下条件:
and/or name =/>//