Spring Data【Spring Data 介绍、Spring Data JPA 、Spring Data JDB】(一)-全面详解(学习总结---从入门到深化)

 

目录

一、 Spring Data 介绍

二、 Spring Data JPA 

三、 Spring Data JDB


一、 Spring Data 介绍

Spring Data 是 Spring 的一个子项目,意在统一和简化对各类型持久化存储和访问, Spring Data 通过一套类似的 API,对关系型数据库、非关系型数据库、搜索引擎等技术进 行 CRUD。

Spring Data 提供了很多的模块去支持各种数据库的操作。如 Spring Data JPA、Spring Data JDBC、Spring Data Redis、Spring Data MongoDB 、Spring Data Elasticsearch、 Spring Data Solr 等,接下来我们分别讲解这些模块的用法。

注:本套课程的所有项目都是基于 SpringBoot 的环境进行搭建,需要各位同学对 SpringBoot 的知识有一定了解。

二、 Spring Data JPA 

1、 概念

Spring Data JPA 是 Spring 在 JPA 规范的基础上,封装的一套 JPA 应用框架,它比 JPA 多了更多的操作方法。

2 、JPA 回顾

JPA 是 JAVA 提供的一款 ORM(对象关系映射)框架,之前我们学过的 ORM 框架有 Mybaits 等。JPA 是一套规范接口,不提供实现,实现由第三方框架提供商。JPA 的主要实现有 Hibernate、EclipseLink 和 OpenJPA 等,开发者只需按照规范中定义的方式来使用 JPA 即可,无论使用哪个实现,开发方式都是一样的。

JPA 操作数据库的方式有使用 EntityManage 自带的方法,使用 JPQL 等。JPA 进行多 表查询与 Mybatis 不同,Mybatis 是面向 SQL 进行多表查询,JPA 则通过@OneToMany、 @ManyToMany 等注解配置对象关系,完成多表查询。

3 、Spring Data JPA 项目搭建

1. 创建 SpringBoot 项目

2. 引入 Spring Data JPA 依赖

<dependencies>
   <!-- springData JPA 的起步依赖 -->
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
   </dependency>
  <!-- MySQL 连接驱动 -->
   <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
   </dependency>
 <!--jdk9 需要导入如下坐标-->
  <dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.0</version>
  </dependency>
</dependencies>

3. 配置文件配置 Spring Data JPA

spring:
  # 配置数据源
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql:///数据库名?serverTimezone=GMT%2b8
    username: root
    password: root
    # 配置 spring data jpa
 jpa:
    database: MySQL
    show-sql: true
    generate-ddl: true
    hibernate:
      ddl-auto: update
      naming_strategy: org.hibernate.cfg.ImprovedNamingStrategy
      # 解决属性使用驼峰命名法无法与数据库字段向匹配
      naming:
         physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

4. 创建实体类:实体类的写法和 JPA 一样。

5. 创建 Repository 接口,该接口需要继承以下两个接口:

         JpaRepository:该接口提供基本的 CRUD 操作

        JpaSpecificationExecutor:该接口提供复杂查询操作

6. 测试,Repository 的常用方法:

         save:新增/修改。如果主键存在,则为修改,否则是新增。

         delete:删除

         findOne:根据 id 查询 

         findAll:查询全部

4 Spring Data JPA 原理

1.SpringDataJPA 通过 JdkDynamicAopProxy 类的 invoke 方法,生成接口的代理对象, 该对象是 SimpleJpaRepository 类型的。

2.SimpleJpaRepository 对象是真正实现 JpaRepository,JpaSpecificationExecutor 的 接口的对象,实现时调用 JPA 的 EntityManage 对象的方法。

3.JPA 的方法是 Hibernate 实现的,Hibernate 实现时调用底层的 JDBC,实现数据库操作。

5 Spring Data JPA 查询方式 

5.1 使用 JpaRepository 接口自带的方法查询

count:查询总记录数

 existsById:查询记录是否存在 

getOne/findById:根据 id 查询

       findById:立即加载

       getOne:延迟加载,测试方法上需要添加事务支持@Transcational

5.2 使用 JPQL 进行查询

在 Repository 接口中定义方法,方法上加@Query(“JPQL”)

 JPQL 中使用 ?参数索引 作为占位符,参数索引从 1 开始

 使用增删改的 JPQL 时,需要在接口方法上加@Modifying

          注:测试增删改的 JPQL 方法时,需要在测试方法上添加事务支持@Transactional, 关闭自动回滚@Rollback(false)

5.3 使用原生 SQL 进行查询

在 dao 接口中定义方法,方法上加@Query(value=“SQL”,nativeQuery=true) 

剩下的用法和 JPQL 一样。

5.4 按照规则命名方法进行查询

只需在 dao 接口中按照 SpringDataJPA 的规则命名方法,该方法就能完成查询。

 规则:查询方法以 findBy 开头,涉及查询条件时,条件的属性用条件关键字连接。

 

5.5 使用 JpaSpecificationExecutor 提供的方法查询 

方法:findAll() 方法参数的含义:

      Specification:查询条件对象

      Pageable:分页条件对象

      Sort:排序条件对象

5.5.1 Specificatio

Specification 是一个接口,通过实现该接口,重写 toPredicate 方法,可以构建一个查询条件对象。

toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb)

root 对象可以获取查询属性对象 Path 对象

cb 对象可以将 Path 对象构造为查询条件对象  

5.5.2 Pageable

Pageable 是一个接口,他有一个实现类 PageRequest,该类对象包含分页参数。通过 PageRequest.of(pageNum,pageSize)方法可以获得 PageRequest 对象,将 PageRequest 对象作为参数传入查询方法,即可获得页面对象 Page。

5.5.3 Sort

Sort 是一个类,创建 Sort 对象可以构建一个排序条件,将 Sort 对象作为参数传入查询方法,会将结果进行排序。

6 领域驱动设计(DDD)

Spring Data JPA 更加符合领域驱动设计(DDD)的项目设计模式。

我们之前构建项目时采用的是数据驱动设计。举个例子,我们现在有一个订单类 (Order)和一个订单详情类(OrderItem)。订单与订单详情是一对多的关系,即一个订 单可以买很多产品,每个产品对应一个详情。设计如下:

public class Order {
    private Long id;
    private Date orderTime; //下单时间
    // ...省略属性
}
public class OrderItem {
    private Long id;
    private Long productId; // 产品 Id
    // ...省略属性
}

之后我们写 OrderDao 类和 OrderItemDao 类负责操作数据库。

假如我们新增了一个订单,我们需要分别调用 OrderDao 和 OrderItemDao 的保存方 法向数据库表中保存 Order 和 OrderItem 的记录。这就是针对数据进行的设计,随时考虑 数据库存什么数据。但如果业务十分复杂,数据驱动设计就会面临维护繁琐的问题,程序员 在操作订单数据时还需了解其他 Dao 的代码,十分浪费精力。

领域驱动模型则是将一整块业务设计为一个领域,比如新增订单业务。该业务需要 Order 和 OrderItem 两类对象,我们将这两类对象称之为聚合。聚合中的操作都是通过聚 合根来完成的,我们可以通过操作 Order 操作聚合中的所有对象,所以 Order 是这个聚合 中的聚合根。代码如下:

@Entity
@Table(name = "bz_order")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String mobile; //下单手机
    @OneToMany(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "order_id", referencedColumnName = "id")
    private List<OrderItem> orderItemList = new ArrayList();
    // 省略其他属性和 getter/setter
}

@Entity
@Table(name = "bz_orderItem")
public class OrderItem {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
        private Long productId; // 产品 Id
        @ManyToOne
        @JoinColumn(name = "order_id",referencedColumnName = "id")
        private Order order;
        // 省略其他属性和 getter/setter
}

 我们只需准备聚合根的 Repository类

public interface OrderRepository extends JpaRepository<Order, Long>, JpaSpecificationExecutor<Order> {}

利用聚合根的 Repository完成整个聚合的操作

Order order = new Order();
order.setMobile("13888888888");
OrderItem orderItem1 = new OrderItem();
OrderItem orderItem2 = new OrderItem();
orderItem1.setProductId(1001L);
orderItem2.setProductId(1002L);
order.getOrderItemList().add(orderItem1);
order.getOrderItemList().add(orderItem2);
orderRepository.save(order);

三、 Spring Data JDB

1 、概念

Spring Data JDBC 是 Spring Data 的子模块,与 Spring Data JPA 功能类似,但更轻 量简单。Spring Data JDBC 不提供缓存,延迟加载等 JPA 功能,这使得 Spring Data JDBC 成为更加简单,有限,灵活的 ORM 框架。且 Spring Data JDBC 支持集成 Mybatis。

2 、Spring Data JDBC 项目搭建 

 2.1. 创建 SpringBoot 项目

 2.2. 引入 Spring Data JDBC 依赖

<dependencies>
   <!-- springData JDBC 的起步依赖 -->
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jdbc</artifactId>
   </dependency>
   <!-- MySQL 连接驱动 -->
   <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
   </dependency>
</dependencies>

3. 写配置文件

spring:
    # 配置数据源
    datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql:///数据库名?serverTimezone=GMT%2b8
    username: root
    password: root

4. 创 建 实 体 类 : 实 体 类 的 写 法 和 Spring Data JPA 类 似 , 但 不 能 使 用@Entity 、 @GeneratedValue 等注解。

5. 创建 Repository 接口,该接口需要继承以下两个接口:

        CrudRepository:该接口提供基本的 CRUD 操作

        PagingAndSortingRepository:该接口提供分页排序查询

6. 测试 Repository 接口的方法

3 Spring Data JDBC 查询方式

 3.1 使用 Repository 接口的方法查询

         使用接口继承的方法查询

         使用@Query(“sql”)自定义查询方法

         按照规则命名方法进行查询

3.2 使用 JdbcTemplate 的方法查询

JdbcTemplate 是 Spring 对原始 JDBC 封装之后提供的一个操作数据库的工具类,他 的使用方式如下:

1. 注入 JdbcTemplate 对象

2. 调用方法

        (1) update(sql 语句,...占位符的参数):执行 DML 语句

        (2) queryForObject(sql , new BeanPropertyRowMapper<>(结果类型.class),...参数):执行查询结果为单行的 DQL 语句

        (3) queryForObject(sql ,结果类型.class,...参数):执行查询结果为单行单列的 DQL 语句。

        (4) query(sql,new BeanPropertyRowMapper<>(结果集合的泛型.class),...参数): 执行结果集为多行的 DQL 语句 

4 Repository 和 Template 的方式对比 

在学习 Spring Data JDBC 时,我们采用了 Repository 和 Template 两种查询方式, Spring Data JPA 也支持 JdbcTemplate 的使用。其实对于 Spring Data 来说,大部分模块 都支持这两种方式查询,那么我们应该如何选用呢?

直接继承 xxxRepository 接口,可以不必自己去写实现类,而轻松实现简单的增删改查、分页、排序等操作,但是对于非常复杂的查询,用起来比较费力。

直接使用 xxxTemplate,需要自己手写 SQL 语句,但是这样增删改查可以自己控制, 对于复杂查询来说,用起来更加得心应手。

一般对于简单的操作,直接继承 Repository 接口,对于复杂操作,使用 Template 完成。

5 Spring Data JDBC 与 Spring Data JPA 对比 

Spring Data JDBC 与 Spring Data JPA 类似,但更轻量简单。Spring Data JPA 的使用必须集成 JPA、Hibernates 等框架,Spring Data JDBC 可以直接使用。Spring Data JDBC不支持 JPQL、缓存、延迟加载等 JPA 功能,但 Spring Data JDBC 可以集成 MyBatis 使用。

6 Spring Data JDBC 集成 MyBatis

Spring Data JDBC 集成 MyBatis 可以使用 Mybatis 缓存、延迟加载等功能,代码如下:

1. 引入 mybatis 起步依赖:

<!-- mybatis-starter -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.1</version>
</dependency>

 2. 创建 Spring Data JDBC 扩展接口

public interface StudentRepositoryExtension {
    List<Student> list();
}

3. mybatis 配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://www.mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tong.springdata.jdbc.StudentRepositoryExtension">
    <!--查询列表-->
    <select id="list" resultType="com.tong.springdata.jdbc.Student">
        select * from bz_student
    </select>
</mapper>

4. Springboot 配置扫描 xml

mybatis:
    mapper-locations: classpath:mapper/*Mapper.xml

5. 使用 mybatis 实现 Spring Data JDBC 扩展接口,此处就可以使用 sqlsession 进行缓存等操作。

@Repository
public class StudentRepositoryExtensionImpl implements StudentRepositoryExtension {
    @Autowired
    private SqlSession sqlSession;
    @Override
    public List<Student> list() {
        return sqlSession.selectList(StudentRepositoryExtension.class.getName() + ".list");
    }
}

 6. StudentRepository 继承扩展接口

public interface StudentRepository extends CrudRepository<Student, Integer>, PagingAndSortingRepository<Student,Integer>,StudentRepositoryExtension

7. 测试

List<Student> list = studentRepository.list();

猜你喜欢

转载自blog.csdn.net/m0_58719994/article/details/132003971