前言
SpringData JPA常用有两种写法,一个是用Jpa自带方法进行 CRUD ,适合简单查询场景、例如查询全部数据、根据某个字段查询,根据某字段排序等等。另一种是使用注解方式, @Query 、 @Modifying 。
1.方法方式
方法说明
接口方法如下,方法作用见注释:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> { // 无条件,查询全部记录 List<T> findAll(); // 排序查询 List<T> findAll(Sort var1); // 根据主键ID查询 List<T> findAllById(Iterable<ID> var1); // 批量保存集合数据 <S extends T> List<S> saveAll(Iterable<S> var1);
void flush();
<S extends T> S saveAndFlush(S var1); // 批量删除 void deleteInBatch(Iterable<T> var1); // all in 全部删除 void deleteAllInBatch(); // 查询一条记录 T getOne(ID var1); // 条件查询 <S extends T> List<S> findAll(Example<S> var1); // 条件查询,带排序 <S extends T> List<S> findAll(Example<S> var1, Sort var2); } |
例子
一般dao实现JpaRepository接口,直接调用JpaRepository中的方法就可以实现了简单查询,例如查询User实例列表:
1 2 3 |
// 构建user的Example对象 Example<User> example =Example.of(User); List<User> users = userRepository.findAll(example); |
2.注解方式
jpa实现CRUD的主要注解是 @Query
注解说明
@Query 注解主要有以下参数,参数作用如下:
value :SQL语句 countQuery : 分页查询时统计总数 nativeQuery : 使用执行这个方法的时候执行原生sql语句,直接写数据库中的 实际表名 和表的 实际字段名@Query 的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
@Retention (RetentionPolicy.RUNTIME) @Target ({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @QueryAnnotation @Documented public @interface Query { String value() default "" ; String countQuery() default "" ; String countProjection() default "" ; boolean nativeQuery() default false ; String name() default "" ; String countName() default "" ; } |
例子
使用注解方式分组查询跟正常写sql语句相同,将sql写到value中,并且 nativeQuery = true 。下面例子是根据 task_id 进行分组查询 task 集合
1 2 |
@Query (value = "select task_id from task group by task_id" , nativeQuery = true ) List<Task> queryByGroup(); |
使用注解方式排序
根据 task_id 进行排序查询 task 集合
1 2 |
@Query (value = "select task_id,task_date from task order by task_id" , nativeQuery = true ) List<Task> queryOrder(); |
使用注解方式条件查询
条件查询时可以使用 字段名 操作符 ? ;例如: task_date >= ? ,使用位置匹配 ? 。也可以使用 字段名 操作符 :属性名 ;例如: task_date >= :startDate ,使用属性名匹配,推荐使用后者,如果字段顺序修改,不影响匹配结果。下面是根据任务时间( task_date )段内和未被删除( deleted )的任务
1 2 |
@Query (value = "select task_id,task_date from task where task_date >=? and task_date <=? and deleted=0 " , nativeQuery = true ) List<ApptTask> queryDate( @Param ( "startDate" ) String startDate, @Param ( "endDate" ) String endDate); |
使用注解方式修改
修改一条数据需要加上 @Modifying 用于标识是修改操作,默认事务等级是只读,所以还需要加上 @Transactional ,这样覆盖了默认的 @Transactional 才可以执行修改操作。下面是根据 task_id 更新 task 表的备注信息
1 2 3 4 |
@Transactional (rollbackOn = Exception. class ) @Modifying @Query (value = "update task set remark = ? where task_id=?" , nativeQuery = true ) void updateRemark( @Param ( "remark" ) String remark, @Param ( "taskId" ) String taskId); |
多表联查,且多条件、分页查询怎么写?
复杂的查询需要注意,以下使用一个Mysql的多表联查的例子来说明复杂的查询要怎么写。下面是 user 表 task 表关联查询出任务名称、任务ID、用户名称这些信息,并且根据 task_name 、 task_date 进行过滤;根据 task_date 倒序。
共有几点需要注意:
多表联查使用正常的JOIN就可以 多条件是常见的情况,需要区别传入的条件是否要去执行,这种情况需要使用 where 1=1 and 这种方式来保证条件不传时仍然正常查询。 分页查询需要传入分页参数 Pageable ,并且写 countQuery 来统计总数。 多条件查询关键: if(:参数!='',k.字段名 =:参数,1=1) ,这里是使用了 if 进行判断,这个写法类似Mybatis xml中的 <if> 标签。 if 的含义是代表传入的参数如果不为""(Spring类型空是""而不是null)将参数传入,如果为空时显示 1=1 代表参数为真,对查询结果不产生作用。代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@Query (value = " select a.task_name, a.task_id,u.user_name" + " from task a " + " LEFT JOIN usert u" + " ON a.user_id = u.user_id" + " where a.deleted=0 " + " AND if(:taskName!='',a.task_name =:taskName,1=1)" + " AND if(:startDate!='',a.task_date >=:startDate,1=1)" + " AND if(:endDate!='',a.task_date <=:endDate,1=1)" + " order by a.task_date desc" , nativeQuery = true , countQuery = " select count(*)" + " from task a " + " LEFT JOIN usert u" + " ON a.user_id = u.user_id" + " where a.deleted=0 " + " AND if(:taskName!='',a.task_name =:taskName,1=1)" + " AND if(:startDate!='',a.task_date >=:startDate,1=1)" + " AND if(:endDate!='',a.task_date <=:endDate,1=1)" + " order by a.task_date desc" ) Page<Map<String,Object>> queryUserTaskPage( @Param ( "taskName" ) String taskName, @Param ( "startDate" ) LocalDate startDate, @Param ( "endDate" ) LocalDate endDate, @Param ( "pageable" ) Pageable pageable); |
小结
以上列举了两种JPA的crud方式,jpa方法与注解方式,平时写代码时更倾向于使用注解方式去写原生sql来实现业务。对于简单查询可以用 JpaRepository 里面这些方法就够用了,对于更复杂的场景推荐使用 @Query 写sql的方式来实现。
jpa方法可以屏蔽底层的sql,如果有不同数据库实现的服务,用jpa方法可以免于修改sql。但是jpa方法对于分组查询、limit支持、多条件、多表联查这些不太友好。
总结
到此这篇关于SpringData JPA常用语法的文章就介绍到这了,更多相关SpringData JPA常用语法内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
原文链接:https://juejin.cn/post/7106487853126778910
查看更多关于SpringData JPA的常用语法汇总的详细内容...