使用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数据层访问内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

详解使用Spring Data repository进行数据层的访问问题的更多相关文章

  1. canvas中普通动效与粒子动效的实现代码示例

    canvas用于在网页上绘制图像、动画,可以将其理解为画布,在这个画布上构建想要的效果。本文详细的介绍了粒子特效,和普通动效进行对比,非常具有实用价值,需要的朋友可以参考下

  2. H5混合开发app如何升级的方法

    本篇文章主要介绍了H5混合开发app如何升级的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  3. canvas学习和滤镜实现代码

    这篇文章主要介绍了canvas学习和滤镜实现代码,利用 canvas,前端人员可以很轻松地、进行图像处理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  4. localStorage的过期时间设置的方法详解

    这篇文章主要介绍了localStorage的过期时间设置的方法详解的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  5. 详解HTML5 data-* 自定义属性

    这篇文章主要介绍了详解HTML5 data-* 自定义属性的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  6. HTML5的postMessage的使用手册

    HTML5提出了一个新的用来跨域传值的方法,即postMessage,这篇文章主要介绍了HTML5的postMessage的使用手册的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  7. 教你使用Canvas处理图片的方法

    本篇文章主要介绍了教你使用Canvas处理图片的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  8. ios – Swift语言:如何调用SecRandomCopyBytes

    从Objective-C,我可以这样做:在Swift中尝试这个时,我有以下内容:但我得到这个编译器错误:data.mutableBytes参数被拒绝,因为类型不匹配,但我无法弄清楚如何强制参数.解决方法这似乎有效:

  9. 使用Firebase iOS Swift将特定设备的通知推送到特定设备

    我非常感谢PushNotifications的帮助.我的应用聊天,用户可以直接向对方发送短信.但是如果没有PushNotifications,它就没有多大意义.它全部设置在Firebase上.如何将推送通知从特定设备发送到特定设备?

  10. ios – NSData to Data swift 3

    如何将此代码转换为使用Swift3数据?

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部