第一章 JPA概述

目录

1、什么是ORM?

2、为什么要用ORM?

3、市场上的ORM框架。

3.1、MyBatis 和 Mybatis-Plus

3.2、Hibernate 和 JPA

3.3、MyBatis 和 JPA 比较

JPA优缺点

Mybatis的优缺点

4、JPA的介绍

5、Spring Data JPA的主要类及结构图

5.1、我们需要掌握和使用到的类。 七个Repository接口:

5.2、两个实现类:

5.3、关系结构图

5.4、需要了解的类,真正的JPA的底层封装类。

6、基于Mysql快速搭建JPA开发实例

  6.1、环境要求

          6.2、创建数据库并建立user表

 6.3、利用Idea创建Example1

 6.4、修改数据库连接,连到mysql数据库。

          6.5、创建model类。

6.6、创建Repository类。

6.7、创建Controller类。

6.7、启动运行。


 

1、什么是ORM?

什么是“持久化” 
持久(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的数据存储在关系型的数据库中,当然也可以存储在磁盘文件中、XML数据文件中等等。

什么是 “持久层” 
持久层(Persistence Layer),即专注于实现数据持久化应用领域的某个特定系统的一个逻辑层面,将数据使用者和数据实体相关联。

什么是ORM

即Object-Relationl Mapping,它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了 。

对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序设计技术,用于实现面向对象编程语言里不同类型系统数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。

2、为什么要用ORM?

为什么要做持久化和ORM设计(重要)

在目前的企业应用系统设计中,MVC,即 Model(模型)- View(视图)- Control(控制)为主要的系统架构模式。MVC 中的 Model 包含了复杂的业务逻辑和数据逻辑,以及数据存取机制(如 JDBC的连接、SQL生成和Statement创建、还有ResultSet结果集的读取等)等。将这些复杂的业务逻辑和数据逻辑分离,以将系统的紧耦 合关系转化为松耦合关系(即解耦合),是降低系统耦合度迫切要做的,也是持久化要做的工作。MVC 模式实现了架构上将表现层(即View)和数据处理层(即Model)分离的解耦合,而持久化的设计则实现了数据处理层内部的业务逻辑和数据逻辑分离的解耦合。 而 ORM 作为持久化设计中的最重要也最复杂的技术,也是目前业界热点技术。

简单来说,按通常的系统设计,使用 JDBC 操作数据库,业务处理逻辑和数据存取逻辑是混杂在一起的。
一般基本都是如下几个步骤:
1、建立数据库连接,获得 Connection 对象。
2、根据用户的输入组装查询 SQL 语句。
3、根据 SQL 语句建立 Statement 对象 或者 PreparedStatement 对象。
4、用 Connection 对象执行 SQL语句,获得结果集 ResultSet 对象。
5、然后一条一条读取结果集 ResultSet 对象中的数据。
6、根据读取到的数据,按特定的业务逻辑进行计算。
7、根据计算得到的结果再组装更新 SQL 语句。
8、再使用 Connection 对象执行更新 SQL 语句,以更新数据库中的数据。
7、最后依次关闭各个 Statement 对象和 Connection 对象。

由上可看出代码逻辑非常复杂,这还不包括某条语句执行失败的处理逻辑。其中的业务处理逻辑和数据存取逻辑完全混杂在一块。而一个完整的系统要包含成 千上万个这样重复的而又混杂的处理过程,假如要对其中某些业务逻辑或者一些相关联的业务流程做修改,要改动的代码量将不可想象。另一方面,假如要换数据库 产品或者运行环境也可能是个不可能完成的任务。而用户的运行环境和要求却千差万别,我们不可能为每一个用户每一种运行环境设计一套一样的系统。
所以就要将一样的处理代码即业务逻辑和可能不一样的处理即数据存取逻辑分离开来,另一方面,关系型数据库中的数据基本都是以一行行的数据进行存取的,而程序运行却是一个个对象进行处理,而目前大部分数据库驱动技术(如ADO.NET、JDBC、ODBC等等)均是以行集的结果集一条条进行处理的。所以为解决这一困难,就出现 ORM 这一个对象和数据之间映射技术。

通俗的将使用ORM拥有两个方面的优势:

1、程序员不需要再去关心和操作数据库的sql语句的增删改查,而是基于对象进行操作处理。

2、基于ORM进行开发的程序,可以更加方便的实现数据库的切换,可以在mysql,oracle,sqlserver以及国产数据之间进行切换。(因为没有原生sql,所以也就没有原生的sql语法)

缺陷:

1、对于之前习惯了使用通过书写sql语句来实现功能的程序员来说,需要接受通过操作对象来进行研发。之前数据库基础无用武之地了。

2、无法使用数据库服务器的高性能处理,如存储过程、表关联查询等。这与将数据库服务器和应用服务器拆分的理念也是相合的。

3、市场上的ORM框架。

3.1、MyBatis 和 Mybatis-Plus

MyBatis本是Apache的一个开源项目iBatis,2010年这个项目由 Apache Software Foundation迁移到了Google Code,并且改名为 MyBatis。MyBatis着力于POJO与SQL之间的映射关系,可以进行更为细致的SQL,使用起来十分灵活,上手简单,容易掌握,所以深受开发者的喜欢,目前市场占有率最高,比较适合互联应用公司的API场景。
 

Mybatis-Plus(简称MP)是一个Mybatis 的增强工具,在 Mybatis的基础上只做增强不做改变,为简化开发、提高效率而生。这是官方给的定义,关于mybatis-plus的更多介绍及特性,可以参考mybatis-plus官网。那么它是怎么增强的呢?其实就是它已经封装好了一些crud方法,我们不需要再写xml了,直接调用这些方法就行,就类似于JPA。

3.2、Hibernate 和 JPA

Hibernate是一个开放源代码的对象关系映射框架,对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲地使用对象编程思维来操纵数据库,并且对象有自己的生命周期,着力对象与对象之间的关系,有自己的HQL查询语言,所以数据库移植性很好。
Hibernate是完备的ORM框架,是符合JPA规范的。Hibernate有自己的缓存机制。从上手的角度来说比较难,比较适合企业级的应用系统开发。
Spring Data JPA可以理解为JPA规范的再次封装抽象,底层还是使用了Hibernate的JPA技术实现,引用JPQL(Java Persistence Query Language)查询语言,属于Spring整个生态体系的一部分。随着Spring Boot和 Spring Cloud在市场上的流行,Spring Data JPA也逐渐进入大家的视野,它们组成有机的整体,使用起来比较方便,加快了开发的效
率,使开发者不需要关心和配置更多的东西,完全可以沉浸在Spring的完整生态标准实现下。JPA上手简单,开发效率高,对对象的支持比较好,又有很大的灵活性,市场的认可度越来越高。
 

3.3、MyBatis 和 JPA 比较

JPA优缺点

优点

  1. 可持久化Java对象。JPA能够直接持久化复杂的Java对象,并能够使用JPQL语言进行复杂的查询。JPQL是JPA专用的查询语言,是类似于SQL的面向对象的查询语言。

  2. 使用简单。JPA使用注释(Annotation)定义Java对象与关系数据库之间的映射,而传统的ORM多使用xml配置文件。JPA使用起来比ORM要方便。使用JPA不用关注底层使用什么数据库。

  3. 规范标准化。JPA是JCP组织发布的,是Java官方规定的统一的API。目前已经有多种框架实现JPA标准。使用了JPA的系统可以自由选择遵循JPA标准的框架,并能够自由更换。

  4. 事务性、大数据量。JPA底层使用关系数据库进行存储,因此具备关系数据库的特点,例如事务性、数据完整性、并发访问、大数据量等。

  5. 与其他持久化技术相比,JPA有很大的技术优势。表列出了JPA与其他持久化技术的比较。

缺点

     因为sql语句是自动生成的可读性是比较差的,对于一些高级业务或者复杂的查询都需要自己来实现sql。

Mybatis的优缺点

优点

上手容易、提供xml标签、支持动态SQL编程,Mapper映射,支持对象与数据库的ORM字段关系映射。

缺点

  1. SQL语句的编写工作量较大,尤其是字段多、关联表多时,更是如此,对开发人员编写SQL语句的功底有一定要求

  2. SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库

  3. 当希望对象的持久化对应用程序完全透明是,不适合使用Mybatis

  4. 当数据库有移植需求或需要支持多种数据库时,不适合使用Mybatis

  5. 缓存使用不当,容易产生脏数据

4、JPA的介绍

Java Persistence API的简称,Java持久层API。 是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。 JPA是一种规范,而Hibernate是JPA的一种实现。

JPA包括以下3方面的内容:

(1)一套API标准。在javax.persistence的包下面,用来操作实体对象,执行CRUD操作,框架在后台替代我们完成所有的事情,开发者从烦琐的JDBC和SQL代码中解脱出来。
(2)面向对象的查询语言:Java Persistence Query Language(JPQL)。这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
(3)ORM(object/relational metadata)元数据的映射。JPA 支持XML和JDK5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中。
 
 

5、Spring Data JPA的主要类及结构图

5.1、我们需要掌握和使用到的类。 七个Repository接口:

 
  1. Repository (org.springframework.data.repository)
  2. CrudRepository (org.springframework.data.repository)
  3. PagingAndSortingRepository (org.springframework.data.repository)
  4. QueryByExampleExecutor (org.springframework.data.repository.query)
  5. JpaRepository (org.springframework.data.jpa.repository)
  6. JpaSpecificationExecutor (org.springframework.data.jpa.repository)
  7. QueryDslPredicateExecutor (org.springframework.data.querydsl)

 5.2、两个实现类:

  1. SimpleJpaRepository (org.springframework.data.jpa.repository.support)
  2. QueryDslJpaRepository (org.springframework.data.jpa.repository.support)

5.3、关系结构图

基本上都是我们要关心的类和接口,先做到心中大体有个数,后面章节我们会一一做讲解。
 

 

5.4、需要了解的类,真正的JPA的底层封装类。

  1. EntityManager (javax.persistence)
  2. EntityManagerImpl (org.hibernate.jpa.internal)

6、基于Mysql快速搭建JPA开发实例

   基于mysql 快速搭建一个Jpa的开发环境。
 

  6.1、环境要求

JDK 1.8  、 Maven 3.5+   、 IntelliJ IDEA
 

  6.2、创建数据库并建立user表

CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `name` varchar(50) DEFAULT NULL,
  `email` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

 

 

 

 

 6.3、利用Idea创建Example1

上面的信息是Maven的pom里面所需要的,都可以修改,如图所示。
 
 
选择JPA、MySQL和Web,一路Next然后完成得到一个工程。完成后结构如图1-9所示。
 
 
 
其他准备工作    创建或者修改application.properties文件。调整启动端口
 
spring.application.name=demo0401
#一般默认端口8080因为怕被占用所以配置为9010 server.port=9010
 
 
 
 
新建文件夹名称,我一般建立config(存放配置) 、common(公共方法)、app(存放应用)、app下新建controller(视图)、model(模型)、repository(数据层)、和service(业务逻辑层)。如果多应用可以在app下再新建appone、two进行分层。
新建一个Hello类确保项目启动。
package com.example.demo0401.app.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/hello")
public class HelloController {
        @RequestMapping("/world")
        public String index(){
            return "Hello World!";
        }
}

 

 
 
 
 
 
 
 
 

 

 

 

 

启动后,访问 http://localhost:9010/hello/world 。 

表示启动成功。

6.4、修改数据库连接,连到mysql数据库。

创建或者修改application.properties文件。
在 工程的sources下面,如 src/main/resources/application.properties。内容如下
 
替换{}包括的内容
 
spring.datasource.url=jdbc:mysql://localhost:3306/{数据库名称}?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password={数据库密码}
 
 
 
 
 
 
 
 
 
 
 

6.5、创建model类。

package com.example.demo0401.app.model;


import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="user")
public class UserPO {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }

}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

6.6、创建Repository类。

 

/**
 * #tableDesc# 数据访问仓库
 *
 * @author #author#
 * @date #now#
 **/

public interface UserRepository extends JpaRepository<UserPO,Integer>,JpaSpecificationExecutor<UserPO>  {

}

 

 

 

 

 

 

 

 

6.7、创建Controller类。

因为为测试,所有未新建业务逻辑和实现类,直接controller调用数据持久层方法。 findAll为jpa默认方法。

@RestController
@RequestMapping("/User")
public class UserController {

    @Autowired
    private UserRepository cloudUserservice;

    @GetMapping("/findAll")
    public JsonResult findAll() {
        return JsonResult.ok(cloudUserservice.findAll());
    }

}

 

 

 

 

 

 

 

 

 

新建统一json返回类

@JsonInclude(JsonInclude.Include.NON_NULL)
public class JsonResult implements Serializable {
   public JsonResult() {
   }
   public JsonResult(boolean flag, String msg) {
      this.flag = flag;
      this.code = "00000";  //默认状态码为0000
      this.message = msg;
      this.data = null;
   }
   public JsonResult(boolean flag, String code, String msg, Object data) {
      this.flag = flag;
      this.code = code;
      this.message = msg;
      this.data = data;
   }
   public JsonResult(Object data) {
      this.flag = true;
      this.code = "00000";
      this.message = "success";
      this.data = data;
   }

   private static final long serialVersionUID = -4177895470291082085L;
   //@ApiModelProperty("成功标志:true成功 false失败")
   private boolean flag;
   // 响应业务状态
   //@ApiModelProperty("业务状态码")
   private String code;
   // 响应消息
   //@ApiModelProperty("业务提示")
   private String message;
   // 响应中的数据
   //@ApiModelProperty("数据")
   private Object data;
   public static long getSerialVersionUID() {
      return serialVersionUID;
   }
   public boolean isFlag() {
      return flag;
   }
   public void setFlag(boolean flag) {
      this.flag = flag;
   }
   public String getCode() {
      return code;
   }
   public void setCode(String code) {
      this.code = code;
   }
   public String getMessage() {
      return message;
   }
   public void setMessage(String message) {
      this.message = message;
   }
   public Object getData() {
      return data;
   }
   public void setData(Object data) {
      this.data = data;
   }

   public static JsonResult ok() {
      return new JsonResult(null);
   }
   public static JsonResult ok(Object data) {
      return new JsonResult(data);
   }
   public static JsonResult ok(String msg, Object obj) {
      return new JsonResult(true, "00000", msg, obj);
   }
   public static JsonResult error(String code, String msg) {
      return new JsonResult(false, code, msg, null);
   }
   public static JsonResult error(String code, String msg, Object obj) {
      return new JsonResult(false, code, msg, obj);
   }

   @Override
   public String toString() {
      StringBuilder builder = new StringBuilder();
      builder.append("JsonResult [flag=").append(flag).append(", code=").append(code).append(", message=").append(message)
            .append(", data=").append(data).append("]");
      return builder.toString();
   }

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

6.7、启动运行。

访问地址:  http://localhost:9010/User/findAll

在数据库给user表添加一行数据,则访问返回数据信息。

这时候已经实现了jpa的第一个方法。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值