详解使用Spring Data repository进行数据层的访问问题

目录
  • 使用Spring Data repository进行数据层的访问
    • 核心概念
    • 查询方法
    • 定义查询方法
    • CREATE
    • USE_DECLARED_QUERY
    • CREATE_IF_NOT_FOUND
    • WEB支持

使用Spring Data repository进行数据层的访问

抽象出Spring Data repository是因为在开发过程中,常常会为了实现不同持久化存储的数据访问层而写大量的大同小异的代码。

Spring Data repository的目的就是要大幅减少这些重复的代码。 Spring Data Elasticsearch为文档的存储,查询,排序和统计提供了一个高度抽象的模板。

核心概念

Spring Data repository抽象中最核心的接口就是Repository。该接口使用了泛型,需要提供两个类型参数,

  • 第一个是接口处理的域对象类型
  • 第二个是域对象的主键类型。

这个接口常被看做是一个标记型接口,用来获取要操作的域对象类型和帮助开发者识别继承这个类的接口。在Repository的基础上,CrudRepository接口提供了针对实体类的复杂的CRUD(增删改查)操作。

public interface CrudRepository<T, ID extends Serializable>
    extends Repository<T, ID> {
    <S extends T> S save(S entity);
    T findOne(ID primaryKey);
    Iterable<T> findAll();
    Long count();
    void delete(T entity);
    boolean exists(ID primaryKey);
    // … more functionality omitted.
}

PagingAndSortingRepository接口在CrudRepository的基础上增加了一些方法,使开发者可以方便的对实体类进行分页和排序。

public interface PagingAndSortingRepository<T, ID extends Serializable>
  extends CrudRepository<T, ID> {
  Iterable<T> findAll(Sort sort);
  Page<T> findAll(Pageable pageable);
}

在分页长度为20的基础上,想要获取第二页的User数据,代码如下

PagingAndSortingRepository<User, Long> repository = // … get access to a bean
Page<User> users = repository.findAll(new PageRequest(1, 20));

查询方法

标准的CRUD(增删改查)功能都要使用查询语句来查询数据库。但通过使用Spring Data,只要五个步骤就可以实现。

  • 创建一个Domain类
@Entity
@Document
public class Person {
  …
}
  • 声明一个继承Repository接口或其子接口的持久层接口。并标明要处理的域对象类型及其主键的类型(在下面的例子中,要处理的域对象是Person,其主键类型是Long)
interface PersonRepository extends Repository<Person, Long> { … }
  • 在接口中声明查询方法(spring会为其生成实现代码)
interface PersonRepository extends Repository<Person, Long> {
  List<Person> findByLastname(String lastname);
}
  • 让Spring创建对这些接口的代理实例。

使用JavaConfig的方式

import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@EnableJpaRepositories
class Config {}

使用xml配置的方式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:jpa="http://www.springframework.org/schema/data/jpa"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans.xsd
     http://www.springframework.org/schema/data/jpa
     http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
   <jpa:repositories base-package="com.acme.repositories"/>
</beans>

注入repository实例,并使用

public class SomeClient {
  @Autowired
  private PersonRepository repository;
  public void doSomething() {
    List<Person> persons = repository.findByLastname("Matthews");
  }
}

定义查询方法

CREATE

Spring Data repository自带了一个非常有用的查询构造器。它会从方法名中去掉类似find..By,read...By,query...By,count...By之类的前缀,然后解析剩余的名字。我们也可以在方法名中加入更多的表达式,比如查询时需要distinct约束,那么在方法名中加入Distinct即可。方法名中的第一个By是一个分解符,代表着查询语句的开始,我们可以用And或Or来将多个查询条件关联起来。

public interface PersonRepository extends Repository<User, Long> {
  List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);
  // Enables the distinct flag for the query
  List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
  List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname);
  // Enabling ignoring case for an individual property
  List<Person> findByLastnameIgnoreCase(String lastname);
  // Enabling ignoring case for all suitable properties
  List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);
  // Enabling static ORDER BY for a query
  List<Person> findByLastnameOrderByFirstnameAsc(String lastname);
  List<Person> findByLastnameOrderByFirstnameDesc(String lastname);
}

除此之外,我们还可以为方法添加某些特定类型的参数(如:Pageable和Sort)来动态的在查询中添加分页和排序。

Page<User> findByLastname(String lastname, Pageable pageable);
Slice<User> findByLastname(String lastname, Pageable pageable);
List<User> findByLastname(String lastname, Sort sort);
List<User> findByLastname(String lastname, Pageable pageable);

USE_DECLARED_QUERY

如果方法通过 @Query 指定了查询语句,则使用该语句创建Query;如果没有,则查找是否定义了符合条件的Named Query,如果找到,则使用该命名查询;如果两者都没有找到,则抛出异常。使用@Query声明查询语句的例子如下:

//使用Query注解
@Query("select a from AccountInfo a where a.accountId = ?1")
public AccountInfo findByAccountId(Long accountId);

CREATE_IF_NOT_FOUND

结合了CREATE和USE_DECLARED_QUERY 两种策略,会先尝试查找声明好的查询,如果没有找到,就按照解析方法名的方式构建查询。这是默认的查询策略,如果不更改配置,会一直使用这种策略构建查询。这种策略支持通过方法名快速定义一个查询,也允许引入声明好的查询。

WEB支持

DomainClassConverter 允许开发者在SpringMVC控制层的方法中直接使用域对象类型(Domain types),而无需通过repository手动查找这个实例。

@Controller
@RequestMapping("/users")
public class UserController {
  @RequestMapping("/{id}")
  public String showUserForm(@PathVariable("id") User user, Model model) {
    model.addAttribute("user", user);
    return "userForm";
  }
}

上面的方法直接接收了一个User对象,开发者不需要做任何的搜索操作,转换器会自动将路径变量id转为User对象的id,并且调用了findOne()方法查询出User实体。 注意:当前的Repository 必须实现CrudRepository

HandlerMethodArgumentResolver使开发者可以在controller的方法中使用Pageable和Sort作为参数。

@Controller
@RequestMapping("/users")
public class UserController {
  @Autowired UserRepository repository;
  @RequestMapping
  public String showUsers(Model model, Pageable pageable) {
    model.addAttribute("users", repository.findAll(pageable));
    return "users";
  }
}

通过上面的方法定义,Spring MVC会使用下面的默认配置尝试从请求参数中得到一个Pageable的实例。

参数名 作用
page 想要获取的页数,默认为0
size 获取页的大小,默认为20
page 需要排序的属性,格式为property,property(,ASC/DESC),默认升序排序。支持多个字段排序,比如?sort=firstname&sort=lastname,asc

开发者也可以针对多个表定义多个Pageable或Sort实例,需要使用Spring的@Qualifier注解来区分它们。并且请求参数名要带有${qualifier}_的前缀。例子如下:

public String showUsers(Model model,
      @Qualifier("foo") Pageable first,
      @Qualifier("bar") Pageable second) { … }

请求中需要带有foo_page和bar_page等参数。

到此这篇关于使用Spring Data repository进行数据层的访问的文章就介绍到这了,更多相关Spring Data repository数据层访问内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring Data JPA框架快速入门之自定义Repository接口

    目录 自定义Repository接口 repository接口定义 使用Repository接口 自定义Repository接口 要定义一个repository接口,你首先需要自定义一个实体类专用的Repository接口.该接口必须扩展 Repository,并将其类型指定为实体类和实体类的 ID 类型. 如果你想为该实体类资源类型开放CRUD方法,请直接继承CrudRepository而不是Repository. repository接口定义 通常,你的repository接口会扩展Repo

  • Spring Data JPA 之 JpaRepository的使用

    目录 1JpaRepository 1.1JpaRepository接口定义 1.2内置方法 1.2.1CrudRepository<T,ID>提供的方法 1.2.2PagingAndSortingRepository<T,ID>提供的方法 1.2.3JpaRepository<T,ID>提供的方法 2方法测试 2.1save 2.2saveAll 2.3findById 2.4existsById 2.5findAll 2.6findAllById 2.7count

  • spring data jpa如何使用自定义repository实现类

    目录 spring data jpa使用自定义repository实现类 创建MyJpaRepository实现类 创建MyJpaRepositoryFactoryBean 配置JPA JPA自定义 Repository 方法 包结构 类与接口之间的关系代码 经过实践发现 spring data jpa使用自定义repository实现类 spring data jpa中使用JpaRepository等接口定义repository时,将默认使用SimpleJpaRepository 可通过自定义

  • 详解Spring Data JPA中Repository的接口查询方法

    目录 1.查询方法定义详解 2.搜索查询策略 3.查询创建 4.属性表达式 5.特殊参数处理 6.限制查询结果 7. repository方法返回Collections or Iterables 8.repository方法处理Null 9.查询结果流 10.异步查询结果 1.查询方法定义详解 repository代理有两种方式从方法名中派生出特定存储查询. 通过直接从方法名派生查询. 通过使用一个手动定义的查询. 可用的选项取决于实际的商店.然而,必须有一个策略来决定创建什么实际的查询. 2.

  • Spring Data Jpa实现自定义repository转DTO

    近期项目中需要 关联 几张表再把字段转出来,在这里记录以下,我感觉网上写的都不太规范和清晰. @Entity @SqlResultSetMapping( name="TestMapping", entities = { @EntityResult( entityClass = com.xxx.xx.data.model.TestEntity.class, fields = { @FieldResult(name="id",column="id")

  • 详解使用Spring Data repository进行数据层的访问问题

    目录 使用Spring Data repository进行数据层的访问 核心概念 查询方法 定义查询方法 CREATE USE_DECLARED_QUERY CREATE_IF_NOT_FOUND WEB支持 使用Spring Data repository进行数据层的访问 抽象出Spring Data repository是因为在开发过程中,常常会为了实现不同持久化存储的数据访问层而写大量的大同小异的代码. Spring Data repository的目的就是要大幅减少这些重复的代码. Sp

  • 详解基于Spring Data的领域事件发布

    领域事件发布是一个领域对象为了让其它对象知道自己已经处理完成某个操作时发出的一个通知,事件发布力求从代码层面让自身对象与外部对象解耦,并减少技术代码入侵. 一. 手动发布事件 // 实体定义 @Entity public class Department implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer departmentId; @Enumerate

  • 微信小程序 详解Page中data数据操作和函数调用

    微信小程序 详解Page中data数据操作和函数调用 Page() 函数用来注册一个页面.接受一个 object 参数,其指定页面的初始数据.生命周期函数.事件处理函数等. //index.js <pre code_snippet_id="2049407" snippet_file_name="blog_20161214_1_1145312" name="code" class="javascript">Page(

  • 详解使用Spring的BeanPostProcessor优雅的实现工厂模式

    最近学习Spring的源码,发现一个利器BeanPostProcessor.这个后置处理器可以在bean初始化前后对bean进行操作.我们可以在初始化的时候对自己想要的bean进行缓存,进而实现自己需要处理的逻辑. 背景 当我们需要根据类型调用接口不同实现的时候,我们可以使用工厂模式实现.下面说下博主遇到过的两次需要使用工厂的场景. 场景一: 当有一个模块,我们需要根据数据库的类型实现不同的的sql.我们此时需要定义一个接口然后每一种数据库实现不同的sql.在调用时根据当前的数据库类型调用对应的

  • Spring Data JPA进行数据分页与排序的方法

    一.导读 如果一次性加载成千上万的列表数据,在网页上显示将十分的耗时,用户体验不好.所以处理较大数据查询结果展现的时候,分页查询是必不可少的.分页查询必然伴随着一定的排序规则,否则分页数据的状态很难控制,导致用户可能在不同的页看到同一条数据.那么,本文的主要内容就是给大家介绍一下,如何使用Spring Data JPA进行分页与排序. 二.实体定义 我们使用一个简单的实体定义:Article(文章) @Data @AllArgsConstructor @NoArgsConstructor @Bu

  • 详解在Spring MVC或Spring Boot中使用Filter打印请求参数问题

    使用Spring MVC或Spring Boot中打印或记录日志一般使用AOP记录Request请求和Response响应参数,在不使用AOP的前提下,如果在Filter中打印日志,在打印或消费请求类型为Content-Type:application/json的请求时,会出现严重的问题. 在Spring体系中,过滤器的定义我们一般采用继承OncePerRequestFilter的方式,当然也可以使用原始的Filter. 错误写法一: 如果不对request和response进行处理,使用伪代码

  • 详解在spring中使用JdbcTemplate操作数据库的几种方式

    使用JdbcTemplate的步骤 1.设置spring-jdbc和spring-tx的坐标(也就是导入依赖) <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.7.RELEASE</version> </dependency> <dependency&

  • 详解用Spring Boot Admin来监控我们的微服务

    1.概述 Spring Boot Admin是一个Web应用程序,用于管理和监视Spring Boot应用程序.每个应用程序都被视为客户端,并注册到管理服务器.底层能力是由Spring Boot Actuator端点提供的. 在本文中,我们将介绍配置Spring Boot Admin服务器的步骤以及应用程序如何集成客户端. 2.管理服务器配置 由于Spring Boot Admin Server可以作为servlet或webflux应用程序运行,根据需要,选择一种并添加相应的Spring Boo

  • 详解Mybatis-plus中更新date类型数据遇到的坑

    最近一年的项目都是在使用Mybatis-plus,感觉挺好用的,也没遇到很多问题,但是在最近项目上线之后,遇到了一些新的需要,在进行新版本开发的时候就开始遇到坑了,今天来说一下更新数据中有date类型数据的时候会出现的问题. 实体类部分字段如下: @Data @Builder @NoArgsConstructor @AllArgsConstructor public class ProductPo implements Serializable { /** * 产品主键,自增 */ privat

  • 详解NumPy中的线性关系与数据修剪压缩

    目录 摘要 一.用线性模型预测价格 二.趋势线 三.数组的修剪和压缩 四.阶乘 摘要 总结股票均线计算原理--线性关系,也是以后大数据处理的基础之一,NumPy的 linalg 包是专门用于线性代数计算的.作一个假设,就是一个价格可以根据N个之前的价格利用线性模型计算得出. 前一篇,在计算均线,指数均线时,分别计算了不同的权重,比如 和 都是按不同的计算方法来计算出相关的权重,一个股价可以用之前股价的线性组合表示出来,也即,这个股价等于之前的股价与各自的系数相乘后再做加和的结果,但是,这些系数是

随机推荐