概念

  • 什么是 JPA

    • JPA(Java Persistence API ): Java 持久化规范的 API 。是 SUN 官方推出的一套基于 ORM 的规范,内部是由一系列的接口和抽象类构成。其提供了一种对象/关系映射工具来管理 Java 应用中的关系数据。
    • JPA 通过 JDK5.0 注解或 XML 描述 对象 - 关系表 的映射关系,并将运行期的实体对象持久化到 DB中。
    • 持久化(Persistence):即把数据保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的对象存储在 DB 中,或者存储在磁盘文件中等。
  • 什么是 Spring Data
    • Spring Data 是一个用于简化数据库访问开源框架。其主要目的是使用数据库访问变得方便快捷。
  • 什么是 Spring Data JPA
    • 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套 JPA 应用框架,可使用极简的代码实现对数据库的访问和操作。
    • 除了 CRUD 外,还包括分页、排序等一些常用的功能,且易于扩展!学习并使用 Spring Data JPA 可以极大提高开发效率。

    相互之间的联系 :

    Spring Data 是一个开源框架,在这个框架中 Spring Data JPA 只是这个框架中的一个模块,所以名称才叫 Spring Data JPA。

    如果单独使用 JPA 开发,会发现这个代码量和使用 JDBC 开发一样繁琐,所以 Spring Data JPA 的出现就为了简化 JPA 的写法,只需要编写一个接口继承一个类就能实现简单 CRUD 操作了。

  • JPA 与 hibernate 的关系

    JPA 规范本质上就是一种 ORM 规范,不是 ORM 框架——因为 JPA 并未提供 ORM 实现,它只是制订了一些规范,提供了一些编程的API接口,但具体实现则由服务厂商来提供实现。

    JPA 和 Hibernate 的关系就像 JDBC 和 JDBC 驱动的关系,JPA 是规范,Hibernate 除了作为 ORM 框架之外,它也是一种 JPA 实现。

    JPA 怎么取代 Hibernate 呢?JDBC 规范可以驱动底层数据库吗?答案是 NO,即是说如果使用 JPA 规范进行数据库操作,底层需要 hibernate 作为其实现类完成数据持久化工作。

  • Spring Data JPA 有什么功能

    Spring Data JPA 提供的核心接口:

    A、Repository:最顶层的空接口,是为了统一所有 Repository 的类型,且能让组件扫描的时候自动识别。

    B、CrudRepository :是 Repository 的子接口,提供 CRUD 的功能。

    C、PagingAndSortingRepository:是 CrudRepository 的子接口,添加分页和排序的功能。

    D、JpaRepository:是 PagingAndSortingRepository 的子接口,增加了一些实用的功能(批量操作等)。

    E、JpaSpecificationExecutor:用来做负责查询的接口。

    F、Specification:是 Spring Data JPA 提供的一个查询规范,要做复杂的查询,只需围绕这个规范来设置查询条件即可。

代码演示

  • A、pom.xml文件

    <?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 http://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.5.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.rookie</groupId>
    <artifactId>jpa</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>jpa</name>
    <description>Demo project for Spring Boot Jpa</description> <properties>
    <java.version>1.8</java.version>
    </properties> <dependencies>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.4</version>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    </dependency>
    </dependencies> <build>
    <plugins>
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    </plugins>
    </build>
    </project>

    这里作者使用的是 springboot 2.1.5.RELEASE 版本,如果使用 2.0.x 以下的版本,会出现某些错误。后边会讲到。

  • B、创建 dto 对象

    @Getter
    @Setter
    @ToString
    @AllArgsConstructor
    @NoArgsConstructor
    @Entity //声明实体类
    @Table(name = "tab_customer") //建立实体类和表的映射关系
    public class Customer implements Serializable{ @Id //声明当前私有属性为主键
    @GeneratedValue(strategy=GenerationType.IDENTITY) //配置主键的生成策略
    private Long id; @Column(name="first_Name") //指定和表中 first_Name 字段的映射关系
    private String firstName; @Column(name="last_Name") //指定和表中 last_Name 字段的映射关系
    private String lastName; public Customer(String firstName, String lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
    }
    }

    常用注解的说明 :

    @Id :指定当前字段是主键。

    @GeneratedValue :指定主键的生成方式。strategy :指定主键生成策略。

    — AUTO主键由程序控制, 是默认选项 ,不设置就是这个。

    — IDENTITY 主键由数据库生成, 采用数据库自增长, Oracle不支持这种方式。

    — SEQUENCE 通过数据库的序列产生主键, MYSQL 不支持。

    — Table 提供特定的数据库产生主键, 该方式更有利于数据库的移植。

    @Entity :指定当前类是实体类。

    @Table :指定实体类和表之间的对应关系。name:指定数据库表的名称

    @Column :指定实体类属性和数据库表之间的对应关系

    ​ 属性:name:指定数据库表的列名称。

    ​ unique:是否唯一 。

    ​ nullable:是否可以为空 。

    ​ inserttable:是否可以插入 。

    ​ updateable:是否可以更新 。

    ​ columnDefinition: 定义建表时创建此列的DDL 。

  • C、创建操作数据的 Repository 对象

    public interface CustomerDao extends JpaRepository<Customer,Long>,JpaSpecificationExecutor {
    }

    对于 JpaRepository 可以从其源码看出:

    CustomerDao 继承了 JpaRepository 之后就拥有了CrudRepository、QueryByExampleExecutor、PagingAndSortingRepository 的基本功能方法了,包括基本的增删改查都有了。

  • D、数据库相关配置 ( application.yml )

    server:
    port: 8088
    spring:
    datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/sample?serverTimezone=UTC&useSSL=false&characterEncoding=UTF8
    username: root
    password: root
    jpa:
    database: mysql
    show-sql: true
    hibernate:
    ddl-auto: create

    注意

    ① 使用 springboot 版本 2.0.x 以上的需要使用如图的 driver-class-name 和 url 中配置serverTimezone=UTC&useSSL=false 否则会报错。不信就试试呗。

    ② 最后一行 ddl-auto : create。此参数是为了方便处理数据库表,该属性的值一般有如下:

    validate : 加载hibernate时,验证创建数据库表结构
    create : 每次加载hibernate,重新创建数据库表结构,这就是导致数据库表数据丢失的原因。
    create-drop : 加载hibernate时创建,退出是删除表结构
    update : 加载hibernate自动更新数据库结构
  • D、为方便演示 demo 起见,在 controller 类中演示。

    @RestController
    @RequestMapping("/customer")
    public class CustomerController { @Autowired
    private CustomerDao customerDao; /**
    * 初始化数据
    */
    @RequestMapping("/index")
    public void index() {
    customerDao.save(new Customer("Jack", "Bauer"));
    customerDao.save(new Customer("Chloe", "O'Brian"));
    customerDao.save(new Customer("Kim", "Bauer"));
    customerDao.save(new Customer("David", "Palmer"));
    customerDao.save(new Customer("Michelle", "Dessler"));
    customerDao.save(new Customer("Bauer", "Dessler"));
    } @RequestMapping("/findAll")
    public void findAll() {
    List<Customer> customerList = customerDao.findAll();
    for (Customer customer : customerList) {
    System.out.println(customer.toString());
    }
    } /**
    * 查询 id 为 1 的数据
    */
    @RequestMapping("/findOne")
    public void findById() {
    Customer customer = customerDao.findById(1L).get();
    if (customer != null) {
    System.out.println(customer);
    }
    } /**
    * 根据 id 删除和批量删除数据
    */
    @RequestMapping("/delete")
    public void delete() { List<Customer> customerList = null; System.out.println("删除前的数据:"); customerList = customerDao.findAll();
    for (Customer customer : customerList) {
    System.out.println(customer.toString());
    } System.out.println("删除ID=3数据:"); customerDao.deleteById(3L); System.out.println("删除后的数据:"); customerList = customerDao.findAll();
    for (Customer customer : customerList) {
    System.out.println(customer.toString());
    }
    }
    }
  • E、控制台会打印如下信息。

    ① 启动项目后,控制台显示建表成功。打印如下语句

    Hibernate: drop table if exists tab_customer
    
    Hibernate: create table tab_customer (id bigint not null auto_increment, first_name varchar(255), last_name varchar(255), primary key (id)) engine=MyISAM

    ② 使用 postman 调用接口 :localhost :8088/customer/index,会插入数据。

    Hibernate: select customer0_.id as id1_0_, customer0_.first_name as first_na2_0_, customer0_.last_name as last_nam3_0_ from tab_customer customer0_
    Hibernate: insert into tab_customer (first_name, last_name) values (?, ?)
    Hibernate: insert into tab_customer (first_name, last_name) values (?, ?)
    Hibernate: insert into tab_customer (first_name, last_name) values (?, ?)
    Hibernate: insert into tab_customer (first_name, last_name) values (?, ?)
    Hibernate: insert into tab_customer (first_name, last_name) values (?, ?)
    Hibernate: insert into tab_customer (first_name, last_name) values (?, ?)

    ③ 使用 postman 调用接口 :localhost :8088/customer/findAll,会查询 DB 中所有数据。

    Hibernate: select customer0_.id as id1_0_, customer0_.first_name as first_na2_0_, customer0_.last_name as last_nam3_0_ from tab_customer customer0_
    
    Customer(id=1, firstName=Jack, lastName=Bauer)
    Customer(id=2, firstName=Chloe, lastName=O'Brian)
    Customer(id=3, firstName=Kim, lastName=Bauer)
    Customer(id=4, firstName=David, lastName=Palmer)
    Customer(id=5, firstName=Michelle, lastName=Dessler)
    Customer(id=6, firstName=Bauer, lastName=Dessler)

    ④ 使用 postman 调用接口 :localhost :8088/customer/delete,会删除 DB 中相应的数据。

    删除前的数据:
    Hibernate: select customer0_.id as id1_0_, customer0_.first_name as first_na2_0_, customer0_.last_name as last_nam3_0_ from tab_customer customer0_
    Customer(id=1, firstName=Jack, lastName=Bauer)
    Customer(id=2, firstName=Chloe, lastName=O'Brian)
    Customer(id=3, firstName=Kim, lastName=Bauer)
    Customer(id=4, firstName=David, lastName=Palmer)
    Customer(id=5, firstName=Michelle, lastName=Dessler)
    Customer(id=6, firstName=Bauer, lastName=Dessler) 删除ID=3数据:
    Hibernate: delete from tab_customer where id=? 删除后的数据:
    Hibernate: select customer0_.id as id1_0_, customer0_.first_name as first_na2_0_, customer0_.last_name as last_nam3_0_ from tab_customer customer0_ Customer(id=1, firstName=Jack, lastName=Bauer)
    Customer(id=2, firstName=Chloe, lastName=O'Brian)
    Customer(id=4, firstName=David, lastName=Palmer)
    Customer(id=5, firstName=Michelle, lastName=Dessler)
    Customer(id=6, firstName=Bauer, lastName=Dessler)

    代码地址 Github :https://github.com/RookieMZL/SpringBoot-JPA

最新文章

  1. sql select 1-10的数字
  2. Aspx页面模拟WebService功能
  3. html,css命名规范 (转)
  4. 修改shell提示符的显示格式
  5. 2016年中国大学生程序设计竞赛(合肥)-重现赛1001 HDU 5961
  6. 类似\u4e0b\u6ce8\u903e\u65f6解码
  7. SQLSERVER:通过sys.tables实现批量删表、快速统计多表记录和
  8. 圣杯VS双飞翼
  9. sqlchemy - day3
  10. 描述cookie,sessionstroage,localstrage的区别
  11. [转]常用的130个vim命令
  12. 查看目标文件是否是以-fPIC编译的, ar 打包命令将多个静态库打包到一个里面
  13. python发送短信和发送邮件
  14. 【转】JAVA反射与注解
  15. axis2与cxf区别
  16. MRTG在Windows平台的安装及使用
  17. Linux 之 tar和nc传文件
  18. Docker入门与应用系列(四)数据卷管理
  19. 无需安装 vsftpd , 直接使用 FTP 来管理 docker 容器中的文件
  20. HTML/JSP中一些单书名号标签的用途&lt;%-- --%&gt;&lt;!-- --&gt;&lt;%@ %&gt;&lt;%! %&gt;&lt;% %&gt;&lt;%= %&gt;

热门文章

  1. Jmeter请求非Json格式的参数如何添加
  2. Jmeter服务器性能压测-用户登录实例CSV方式
  3. MHA + proxysql 高可用以及读写分离
  4. ApiCloud如何一键真机测试
  5. shell脚本编写监控内存并发送邮件
  6. C/C++ volatile
  7. Yii2中应用子模块下的内容
  8. 收集python2代码转python3遇到的问题
  9. targetSdkVersion和与target属性的区别
  10. error LNK2019: 无法解析的外部符号 _PhInitializePhLib,该符号在函数 _EnumHandle 中被引用