SpringData JPA

       前言

        Spring Data JPA 可以极大地简化 JPA 的写法, 可以在几乎不用写实现的情况下,实现对数据的访问操作 。除了 CRUD 外 ,还包括如分页、排序等一些常用的功能。Spring Data 是一个开源框架,如果单独使用 JPA 开发,你会发现代码量少得有点惊人,Spring Data JPA 的出现就是为了简化 JPA 的写法,让开发者只需要编写一个接口、继承一个类就能实现 CRUD 操作


JPA

        JPA(Java Persistence API)是一种Java应用程序接口规范。用来实现Java数据持久化。

  • JDBC和JPA

    JPA和JDBC类似都是一种持久化的接口和规范。JDBC是面向SQL,实现持久化比较繁琐。所以就有了 ORM 框架,建立了 Java 对象与数据库表之间的映射关系,可以通过直接操作对象来实现持久化,简化了操作的繁杂度。而 JPA 就是 ORM 框架的规范。HiBernate框架刚好是符合 JPA 规范的,而 MyBatis 却不符合,因为 MyBatis 还是需要写 SQL 的。


SpringData简介

        SpringData是Spring的一个子项目,用于简化数据库访问,包括 NoSQL 非关系型数据库,另外还包括对关系型数据库的访问支持。SpringData 使我们可以快速简单地使用普通的数据访问技术及新的数据访问技术,SpringData 会让数据的访问变得更加方便。

Spring Data JPA 只是 SpringData 框架中一个模块,所以称为 Spring Data JPA。

  • 统一的 Repository 接口

upload successful

  • 提供了数据访问模板类 xxxTemplate;

    MongoTempalate访问 MongoDB 数据库。

    RedisTemplate访问 Redis 非关系型数据库。

upload successful

  • SpringData实现数据访问的原理解析

    有了 SpringData 后,我们的应用程序 Application 只需要面向 SpringData 编程,我们只要将 SpringData 给我们提供的统一数据访问 API 用好即可,比如提供的 Repository Support、Templates、Object Mapping,我们只要用好它们即可。

  • JPA 与 与 Spring Data

    • JpaRepository的基本功能

      在 DAO 层编写接口继承 JpaRespository 既有 crud 及分页等基本功能。

    • @Query自定义查询,定制查询 SQL

整合 JPA
  • SpringBoot 整合 JPA

    CrudRepository接口源码。

    upload successful

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
         <version>2.1.8.RELEASE</version>
         <relativePath/>
         <!-- lookup parent from repository -->
        </parent>
        <groupId>com.example</groupId>
        <artifactId>demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>demo</name>
        <description>Demo project for Spring Boot</description>
        <properties>
            <java.version>1.8</java.version>
        </properties>
        <dependencies>
            <!--START 添加 Spring Data JPA 依赖 START-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                     <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <!--START 添加 JDBC 依赖 START-->
            <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>
         <!--START 添加 spring-boot-starter-web 依赖 START-->
            <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--START 添加 MySQL 依赖 START-->
            <dependency>
               <groupId>mysql</groupId>
               <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>                                                    <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <!--START 添加 thymeleaf 依赖 START-->
            <dependency>
              <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    • 创建持久化类 - pojo包

      upload successful

    • 定义数据访问层接口 - dao包

      upload successful

    • 定义业务层类

      upload successful
      upload successful

    • 定义控制器类

      upload successful

  • PagingAndSortingRepository

    pagingAndSortingRepository 继承自 CrudRepository 接口,除了拥有 CrudRepository 接口的所有功能之外,PadingAndSortingRepository 接口还提供了分页与排序功能。PadingAndSortingRepository 接口的源码如下所示。

    upload successful

  • PagingAndSortingRepository接口使用

    在使用中其他的布局方式与CrudRepository接口布局方式相同,实体类中需要实现序列化接口Serializable。dao包中所继承的接口把CrudRepository换成pagingAndSortingRepository即可。

  • 简单条件查询语句

    修改dao连接的接口使用为JpaRepository<T,ID>。该接口继承了CrudRepository和其他接口的能力,并新增了更多的方法。

upload successful

这些方法并不是JpaRepository接口所有的方法,但JpaRepository等同于JPQL可以根据方法名,返回相应的查询语句。

关键字 例子 SQL说明
And findByNameAndAddress Where s.name = ?1 And s.address = ?2
Or findByNameOrAddress Where s.name = ?1 Or s.address = ?2
Like findByNameLike Where s.name like ? 1
NotLike findByNameNotLike Where s.name not like ?1
Between findByAgeBetween Where s.age between ?1 and ?2
LessThan findByAgeLessThan Where s.age < ?1
LessThanEqual findByAgeLessThanEqual Where s.age <= ?1
GreaterThan findByAgeGreaterThan Where s.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual Where s.age >= ?1
OrderBy findSexOrderByAgeDesc Where s.sex=?1 order by s.age desc
In findByAgeIn(Collection ages) Where s.age in ?1
IsNull findByAgeIsNull Where s.age is null
After findByStartDateAfter Where s.startDate > ?1
Before findByStartDateBefore Where s.startDate < ?1
  • 关联查询和@Query查询

    • 实现双向多对一关联

        //House房屋表关联街道
      @ManyToOne(fetch = FetchType.LAZY,targetEntity = Street.class,cascade = {CascadeType.ALL})
       @JoinColumn(name = "street_id")
         private Street street;
      
       @OneToMany(fetch = FetchType.LAZY,targetEntity = House.class,mappedBy = "street",cascade = {CascadeType.ALL})
      private Set<House> houses = new HashSet<>();
    • @Query查询

      public interface HouseRepository extends JpaRepository<House,Integer> {
          @Query("from House")
          List<House> queryAll();
      
       @Query("select * from House h where h.name = ?1")
       List<House> findNameByHouseName(String name);
      
       @Query("select * from House h where h.name =:name")
       List<House> findNameByHouseName(String name);
      }