Spring Boot 2.0 读书笔记_09:Spring Data JPA 上

版权声明:未经博主本人同意,请勿私自转发分享。 https://blog.csdn.net/Nerver_77/article/details/85131353

6. Spring Data JPA 上

JPA

经过上篇文章从封装角度上对数据库操作的叙述,很好的为下文JPA操作做了铺垫。

这个地方需要注意的是 Spring Data JPA 不是一个名词,Spring DataJPA两个的集成哦!

Spring Data JPA,在JPA提供的简单语义上做了一定程度的封装,满足基本CURD的操作需求。此外,Spring Data为Spring框架对访问SQL和NoSQL数据库提供了一致的方式。

Spring Data:数据库交互的方式

关键字:Spring官方提供一套数据层综合解决方案

Spring Data 是为数据访问提供熟悉且一致的基于Spring的编程模型,同时仍保留底层数据存储的特殊特性。在关系数据库和非关系数据库,map-reduce框架以及基于云的数据服务变得很容易。旨在统一和简化对各类型持久化存储和访问,使得对数据库的访问变得方便快捷。

JPA:Java持久层API(Java Persistence API)

关键字:ORM规范

JPA本质是一种ORM规范(为JPA并未提供ORM实现,只是制定了规范)。只是提供了一些相关的接口,但是接口并不能直接使用,需要实现容器。

Hibernate 从3.2开始,就开始兼容JPA。Hibernate3.2获得了Sun TCK的 JPA(Java Persistence API) 兼容认证。

JPA和Hibernate之间的关系,可以简单的理解为JPA是标准接口,Hibernate是实现,并不是一对一关系。Hibernate属于遵循JPA规范的一种实现,但是JPA是Hibernate遵循的规范之一,Hibernate还有其他实现的规范。
在这里插入图片描述
简单来讲就是:ORM框架的实现遵循包括JPA(ORM规范)在内的多个规范。反过来讲,JPA(ORM规范)同样适用于多种ORM框架。


而本章的主角:Spring Data JPA 便是Spring官方所给出的一种数据库访问操作的解决方案。

Spring Data JPA, part of the larger Spring Data family, makes it easy to easily implement JPA based repositories. This module deals with enhanced support for JPA based data access layers. It makes it easier to build Spring-powered applications that use data access technologies.
Implementing a data access layer of an application has been cumbersome for quite a while. Too much boilerplate code has to be written to execute simple queries as well as perform pagination, and auditing. Spring Data JPA aims to significantly improve the implementation of data access layers by reducing the effort to the amount that’s actually needed. As a developer you write your repository interfaces, including custom finder methods, and Spring will provide the implementation automatically.

官方说明中表明:Spring Data JPA会使得基于数据库的JPA规范更加的简单高效。

上面也提到了JPA采取了Hibernate的框架层面的实现,那么这里的JPA(ORM规范)的数据库封装角度也是基于Java Entity的。

虽然上述的说明有些拗口,但是我们可以认为Spring Data JPASpring官方所给出的一种ORM框架


废话不多说,开整!

Spring Boot 集成 Spring Data JPA,添加依赖即可开始我们的Spring Data JPA之旅。

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

前期配置:
配置文件:application.properties

  spring.datasource.url=jdbc:mysql://127.0.0.1:3306/orm?useUnicode=true&characterEncoding=UTF-8
  spring.datasource.username=root
  spring.datasource.password=1234
  spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
  spring.jpa.show-sql =true

配置类:DataSourceConfig.java,连接池方面采用了Hikari

@Configuration
public class DataSourceConfig {

    @Bean(name = "dataSource")
    public DataSource datasource(Environment env) {
        HikariDataSource ds = new HikariDataSource();
        ds.setJdbcUrl(env.getProperty("spring.datasource.url"));
        ds.setUsername(env.getProperty("spring.datasource.username"));
        ds.setPassword(env.getProperty("spring.datasource.password"));
        ds.setDriverClassName(env.getProperty("spring.datasource.driver-class-name"));
        return ds;
    }
}

配置JPA支持:Spring Data JPA 采用了 Hibernate 实现,需要关注两个特性

  1. spring.jpa.hibernate.ddl-auto:是否自动建库。默认为none,Hibernate 能根据 Entity的定义自动生成表以及修改己有的表和表主键设置等。
  2. spring.jpa.show-sql:是否打印SQL。默认为false,这里我们设置为true,我们需要看到数据库操作的SQL语句。

Java Entity配置(不同于常用的POJO类)

封装角度从Java Entity出发的JPA,自然对Java Entity的配置是很严格了!
JPA提供了很多注解进行配置Java Entity,这里列举下常用的注解类型并给出例子。

@Entity
public class User  {

  @Id
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  private Integer id;

  // 部门
  @Column
  private String name;

  // 创建时间
  @Column(name="create_time")
  private Date createTime ;
  
  // 部门
  @ManyToOne
  @JoinColumn(name="department_id")
  Department department;

  public User() {
    // 默认无参构造函数必须有
  }

  // getter and setter func etc..
}
注解 说明 备注
@Entity 实体POJO类必须使用的标识注解
@Id 声明该成员属性映射到数据库表的主键字段
@GeneratedValue 数据库主键生成策略 IDENTITY:采用数据库ID自增长的方式来自增主键字段,Oracle 不支持这种方式。
AUTO: JPA自动选择合适的策略,是默认选项。
SEQUENCE:通过序列产生主键,通过@SequenceGenerator 注解指定序列名,MySql不支持这种方式。
TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。
@Column 表明成员属性与数据库表字段对应 name属性可指定字段名(适用于属性与字段名不一致情况)
@ManyToOne Many 指的是该定义成员变量的实体,即User实体。
One 指的是该注解所注解的成员属性,即Department实体。
ManyToOne 说明对象 User 和 Department 的冠以是多对一的关系。即,多个用户属于一个部门。
@OneToMany 反之同理
@JoinColumn 与@ManyToOne结合使用,说明外键字段是department_id

@OneToMany举例:

@Entity
punlic class Department {
  
  @OneToMany(mappedBy="department")
  private Set<User> users = new HashSet<User>();

  public Department () {}

  // getter and setter func etc..
}

Department实体中存在一个users成员变量,且类型是Set[表示集合元素无序]。@OneToMany注解表明一个部门具有多个用户。这里还需要注意:在一对多的关系映射上,One端采用@OneToMany注解时必须使用mapperBy属性声明Many端的对象[User]的department属性提供了对应的关系映射。

上述是完整的Java Entity 配置项,当然现在的越来越多的JPA应用采用了简化的Entity定义,去掉了关系映射的相关配置和数据库外键的相关配置。

Repository

RepositorySpring Data 的核心概念,抽象了对数据库和NoSQL的操作。提供了几个常用接口供我们使用:

  • Repository: 最顶层的接口,是一个空接口,目的是为了统一所有的Repository的类型,且能让组件扫描时自动识别。
  • CrudRepository:提供了基本的CURD,批量操作接口。
  • PagingAndSortingRepository:集成CrudRepository,提供分页排序等功能。
  • JpaRepository:JPA专用,提供更多丰富的数据库访问接口。

那它们的之间的关系如图:接口间的的逐级继承
在这里插入图片描述
这里还提到了Spring Data操作数据库和NoSQL库NoSQL库主要包括:Redis、MongoDB、Elasticsearch。

在Spring官网上可以看到这些项目的介绍和使用如图:
在这里插入图片描述
接下来分别对常用接口进行说明:

  • CrudRepository:实现Entity的基本CURD操作功能。

    @org.springframework.data.repository.NoRepositoryBean
    public interface CrudRepository <T, ID> extends org.springframework.data.repository.Repository<T,ID> {
        
      // save 保存 entity,如果Entity包含主键,则认为是更新操作
      <S extends T> S save(S s);
    
      <S extends T> java.lang.Iterable<S> saveAll(java.lang.Iterable<S> iterable);
    
      // findById 根据主键查询实体 返回Optional对象        
      java.util.Optional<T> findById(ID id);
    
      // existsById 根据主键返回对象是否存在
      boolean existsById(ID id);
    
      java.lang.Iterable<T> findAll();
    
      java.lang.Iterable<T> findAllById(java.lang.Iterable<ID> iterable);
    
      // 返回Entity个数
      long count();
    
      // deleteById 根据主键删除Entity
      void deleteById(ID id);
    
      // 删除实体
      void delete(T t);
    
      void deleteAll(java.lang.Iterable<? extends T> iterable);
      // 删除全部实体
      void deleteAll();
    }
    

    T表示实体类,ID表示主键封装类,ID必须实现序列化接口。类似DAO接口和XML映射文件的关系。

    public interface UserRepository extends CrudRepository<User, Integer> { }
    
  • PagingAndSortingRepository:增加了分页和排序相关的操作功能。

    @org.springframework.data.repository.NoRepositoryBean
    public interface PagingAndSortingRepository <T, ID> 
        extends org.springframework.data.repository.CrudRepository<T,ID> {
        
      // 按照 Sort 指定的排序返回所有实体
      java.lang.Iterable<T> findAll(org.springframework.data.domain.Sort sort);
      
      // Pageable 构造了查询的翻页参数,Page 表示了查询的具体结果。[查询结果集相关数据]
      org.springframework.data.domain.Page<T> findAll(org.springframework.data.domain.Pageable pageable);
    }
    
  • JpaRepository:提供了更多使用的功能,以及通过Example对象进行查询。

    @NoRepositoryBean
    public interface JpaRepository<T, ID> 
            extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
    
      // 保存或更新一组实体
      <S extends T> List<S> saveAll(Iterable<S> entities);
    
      // 批量删除一组实体
      void deleteInBatch(Iterable<T> entities);
    
      // 查询满足 example 条件的所有对象
      <S extends T> List<S> findAll(Example<S> example);
    
      // 查询满足 example 条件的所有对象,并按照 Sort 对象的排序规则进行排序。
      <S extends T> List<S> findAll(Example<S> example, Sort sort);
    }
    

猜你喜欢

转载自blog.csdn.net/Nerver_77/article/details/85131353
今日推荐