SpringdataJpa JpaRepository

接口继承

持久层接口继承 Repository并不是唯一选择。Repository 接口是 Spring Data 的一个核心接口,它不提供任何方法,开发者需要在自己定义的接口中声明需要的方法。与继承Repository 等价的一种方式,就是在持久层接口上使用 @RepositoryDefinition 注解,并为其指定 domainClass 和idClass 属性。

1.如果持久层接口较多,且每一个接口都需要声明相似的增删改查方法,直接继承 Repository 就显得有些啰嗦,这时可以继承 CrudRepository,它会自动为域对象创建增删改查方法,供业务层直接使用。开发者只是多写了 "Crud" 四个字母,即刻便为域对象提供了开箱即用的十个增删改查方法。

2.使用 CrudRepository 也有副作用,它可能暴露了你不希望暴露给业务层的方法。比如某些接口你只希望提供增加的操作而不希望提供删除的方法。针对这种情况,开发者只能退回到 Repository 接口,然后到 CrudRepository 中把希望保留的方法声明复制到自定义的接口中即可.

3.分页查询和排序是持久层常用的功能,Spring Data 为此提供了 PagingAndSortingRepository 接口,它继承自 CrudRepository 接口,在 CrudRepository 基础上新增了两个与分页有关的方法。但是,我们很少会将自定义的持久层接口直接继承自 PagingAndSortingRepository,而是在继承 Repository CrudRepository 的基础上,在自己声明的方法参数列表最后增加一个 Pageable Sort 类型的参数,用于指定分页或排序信息即可,这比直接使用 PagingAndSortingRepository 提供了更大的灵活性。

4.JpaRepository 是继承自 PagingAndSortingRepository 的针对 JPA 技术提供的接口,它在父接口的基础上,提供了其他一些方法,比如 flush()saveAndFlush()deleteInBatch() 等。如果有这样的需求,则可以继承该接口。

查询方式

 1.通过解析方法名创建查询

框架在进行方法名解析时,会先把方法名多余的前缀截取掉,比如find、findBy、read、readBy、get、getBy,然后对剩下部分进行解析。并且如果方法的最后一个参数是 Sort 或者 Pageable类型,也会提取相关的信息,以便按规则进行排序或者分页查询。

在创建查询时,我们通过在方法名中使用属性名称来表达,比如findByUserAddressZip ()。框架在解析该方法时,首先剔除findBy,然后对剩下的属性进行解析,详细规则如下(此处假设该方法针对的域对象为 AccountInfo 类型):

先判断userAddressZip (根据 POJO 规范,首字母变为小写,下同)是否为 AccountInfo的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,继续第二步;

从右往左截取第一个大写字母开头的字符串(此处为Zip),然后检查剩下的字符串是否为 AccountInfo的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,则重复第二步,继续从右往左截取;最后假设 user 为 AccountInfo 的一个属性;

接着处理剩下部分(AddressZip ),先判断 user 所对应的类型是否有 addressZip 属性,如果有,则表示该方法最终是根据"AccountInfo.user.addressZip" 的取值进行查询;否则继续按照步骤 2 的规则从右往左截取,最终表示根据"AccountInfo.user.address.zip" 的值进行查询。

在查询时,通常需要同时根据多个属性进行查询,且查询的条件也格式各样(大于某个值、在某个范围等等),SpringData JPA 为此提供了一些表达条件查询的关键字,大致如下:

  • And --- 等价于 SQL 中的 and 关键字,比如 findByUsernameAndPassword(String user, Striang pwd)
  • Or --- 等价于 SQL 中的 or 关键字,比如 findByUsernameOrAddress(String user, String addr)
  • Between --- 等价于 SQL 中的 between 关键字,比如 findBySalaryBetween(int max, int min)
  • LessThan --- 等价于 SQL 中的 "<",比如 findBySalaryLessThan(int max)
  • GreaterThan --- 等价于 SQL 中的">",比如 findBySalaryGreaterThan(int min)
  • IsNull --- 等价于 SQL 中的 "is null",比如 findByUsernameIsNull()
  • IsNotNull --- 等价于 SQL 中的 "is not null",比如 findByUsernameIsNotNull()
  • NotNull --- IsNotNull 等价;
  • Like --- 等价于 SQL 中的 "like",比如 findByUsernameLike(String user)
  • NotLike --- 等价于 SQL 中的 "not like",比如 findByUsernameNotLike(String user)
  • OrderBy --- 等价于 SQL 中的 "order by",比如 findByUsernameOrderBySalaryAsc(String user)
  • Not --- 等价于 SQL 中的 " =",比如 findByUsernameNot(String user)
  • In --- 等价于 SQL 中的 "in",比如 findByUsernameIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;

  • NotIn --- 等价于 SQL 中的 "not in",比如 findByUsernameNotIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;

@Query注解

1、只使用注解

@Query(value= "select name,author,price from Book b where b.price>?1 andb.price<?2")
List
<Book> findByPriceRange(long price1, long price2);

 

2、使用Native SQLQuery

所谓本地查询,就是使用原生的sql语句(根据数据库的不同,在sql的语法或结构方面可能有所区别)进行查询数据库的操作。

@Query(value ="select * from book b where b.name=?1", nativeQuery =true)
List<Book> findByName(String name);

 

3、使用@Param注解注入参数

@Query(value ="select name,author,price from Book b where b.name = :name ANDb.author=:author AND b.price=:price")
List<Book> findByNamedParam(@Param("name") String name,@Param("author") String author,@Param("price") long price);

 

4、SPEL表达式

'#{#entityName}'值为'Book'对象对应的数据表名称(book)

@Query(value ="select * from #{#entityName} b where b.name=?1", nativeQuery = true)

List<Book>findByName(String name);


分页查询

1、设置排序规则

Sort sort = new Sort(Sort.Direction.DESC, "id");  

2、设置分页信息(当前页,每页大小,排序规则)

Pageable pageable = new PageRequest(page, size, sort);  

3、查询数据库获取内容

Page<User> pages=userDao.findByName(name,pageable);  

4、获取集合信息

List<User> userList = page.getContent();


猜你喜欢

转载自blog.csdn.net/black_cheng/article/details/78484468