• [spring] spring jpa - hibernate 名词解释&配置


    [spring] spring jpa - hibernate 名词解释&配置

    之前过了一遍依赖注入的内容,这次过一下数据相关的部分,完成了这部分内容,下篇就涉及到 API 实现了

    操作的部分放到下一篇,本篇主要是概念+配置

    整体课程上来说,已经完成了将近 1/3,年底之前应该说可以把 spring boot 相关的内容滚完

    名词解释

    在开始用 jpa/hibernate 之前,先开始解释一些名词

    • MVC

      MVC 和 spring 没有直接的关联,这是一个更加广泛的,关于 Model-View-Controller 设计模式,其中:

      • Model

        代表数据和业务逻辑相关内容,简单的说就是负责和数据库交流,并且进行数据更新的部分

      • View

        渲染层,直接和用户进行互动的部分,包括从后台获取数据,在前台和用户互动,并且获取用户输入,传输到后台

      • Controller

        负责沟通 model 和 view 的桥梁,将从 view 接收到的数据传给 model 进行数据更新,将从 model 获取的数据传给前台进行渲染

      一些比较流行的 MVC 框架有 Ruby,Django(python),Spring MVC(java)express(js),ASP .NET MVC(C#)

    • SSH

      Struts-Spring-Hibernate 框架的缩写,其中 Struts 代表着 View 结构,Spring 是负责 Controller+Model,而 Hibernate 则负责协助和数据库沟通,也是 Model 的一部分

    • SSM

      即 Spring+Spring MVC+Mybatis

      这里 Spring 也是负责 Controller+Model 部分,Spring MVC 负责渲染,而 Mybatis 代替了 Hibernate,负责协助数据库的沟通

    • ORM

      Object-Relationship Mapping

      使用该框架可以通过映射对象(Object)与关系型数据库(Relational DB),让开发者免于写 SQL,而是直接对对象进行操作即可

      比较流行的 ORM 有:Hibernate(Java),ActiveRecord(Ruby),Django’s ORM(Python),Entity Framework(.Net),Sequelize(JS,Node)

    • Mybatis

      Mybatis 是 SQL 映射框架,学习门槛较低,上手较快,因此在 SSM 框架中占据一席之地

      基本上说 Mybatis 可以缩短写开发要写的 SQL,并且 MyBatis 负责与数据库进行沟通,提供比较高的灵活性

      使用 MyBatis,开发者还是需要写自己的 SQL 的,它并不是一个 ORM 框架

    • Hibernate

      Hibernate 是一个 ORM 框架,因此可以让开发者只操作 Java 对象,而 Hibernate 负责和数据库进行沟通

      简而言之就是,Hibernate 借将对应的 java 对象与数据库进行映射,并实现 SQL 操作

      Hibernate 是 Spring Boot 的默认 JPA Provider,它本质上还是调用 JDBC 去实现具体的数据库操作

    • JPA

      Java Persistence API 的缩写,这是 API 规范,Hibernate 就是实现了 JPA 的 ORM 框架

      换言之,除了 Hibernate 之外,还有其他的框架也实现了 JPA,如 EclipseLink

      ⚠️:JPA 好像已经改名成了 Jakarta Persistence API

    • Spring JPA

      提供了 boilerplate code 用来加速 JDBC 的操作

      使用 Spring JPA 必须要有一个 JPA provider,比较流行的 provider 就是 Hibernate

      没有 Provider,Spring JPA 无法实现和数据库的沟通

    这样大概就能解释一点 JPA、Spring JPA 和 Hibernate 之间的关系了……?

    配置

    配置 spring initializr

    主要就是额外加了两个 dependencies:

    在这里插入图片描述

    配置数据库

    配置数据库这块主要是从 application.properties 里面配置,我配置的内容如下:

    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/student_tracker
    spring.datasource.username=springstudent
    spring.datasource.password=springstudent
    # deprecated
    #spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
    # use org.hibernate.dialect.MySQLDialect instead
    spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这个配置还是比较简单的,运行结果如下:

    在这里插入图片描述

    补充一下: 我创建了对应的用户和密码,没有创建的话,使用默认的用户名和密码 root 也可以

    配置中可能遇到的问题

    虽然这个步骤很快,但是实际上我在这一步卡了半天,主要碰到下面几个问题:

    1. 缺少 dialect

      教程里给的配置没有 spring.jpa.database,后面 Google 了一下加了 MySQL8Dialect

    2. typo

      应该是 org.hibernate.dialect.MySQL8Dialect,我漏了个 org

    3. 数据库不 match

      教程里用的是 MySQL,我本地的数据库是 MariaDB v11

      后面我试着切换 MariaDB 106 的 Dialect,然后发现 POM 又要更新,折腾若干次未果,后面还是重新下载了一个 MySQL 才跑通

      所以说,数据库的版本还是要和 Hibernate 提供的 Dialect 符合,我怀疑 MariaDB11 和 106 不兼容(因为有个大版本的差别)

    4. 本地重装数据库冲突

      MariaDB 曾经是 MySQL 的套壳,不过现在两个差别越来越大了……

      brew 卸载 maria 的话还是删的比较干净的,不过删 MySQL 的时候有个残存的文件夹,这样我重新下载其他的 DB(Maria/MySQL)就会启动失败,解决方案是彻底删除残留的文件夹,再重新安装就好了

      我用的脚本为:

      ❯ brew uninstall mysql
      ❯ rm -Rf /usr/local/var/mysql
      ❯ brew install mysql
      ❯ mysql.server start
      
      • 1
      • 2
      • 3
      • 4

    配置完成了后,spring boot 就会根据配置自动创建对应的 DataSource, EntityManager 等数据库相关的 bean

    项目配置

    因为 CRUD 的操作比较麻烦,所以教程里面使用的是 CLI,具体内容如下:

    package com.example.hibernatejpa;
    
    import com.example.hibernatejpa.dao.StudentDAO;
    import com.example.hibernatejpa.entity.Student;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    
    @SpringBootApplication
    public class HibernateJpaApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(HibernateJpaApplication.class, args);
    	}
    
    	@Bean
    	public CommandLineRunner commandLineRunner(StudentDAO studentDAO) {
    
    		return runner -> System.out.println("Hello World");
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    commandLineRunner 主要是在 Spring 启动后会执行一些命令行输出语句,比如说这里就 log 了一下 Hello World:

    在这里插入图片描述

    这里也可以修改一下 properties 文件,减少一点 log 的输出:

    spring.main.banner-mode=off
    logging.level.root=warn
    
    • 1
    • 2

    修改了之后,info 相关的内容和 Spring 的 banner 就不会被输出了:

    在这里插入图片描述

    JPA 注解

    一些本篇笔记会用到的注解如下:

    • Entity Mapping

      @Entity, @Table

    • Primary Key

      @Id, @GeneratedValue

    • Columnh Mapping

      @Column

    • Relationship

      这个案例里暂时不会用到,不过是这种关系:@OneToOne

    • Query

      @NamedQuery

    • 来自 Spring

      @Transactional 代表这会对数据进行 mutation,这里面具体操作还挺复杂的,涉及到 rollback 等操作,之后看看课程里会不会讲,不会的话我抽空研究一下

    这种很多,不过用到了再了解就是了

    一些类,如 EntityManager, DataSource,Spring 会根据配置自动生成,后面直接拿来用就好了

    操作流程如下:

    1. 定义 Entity Object

      JPA 会将这个类与数据库中的 entity 进行 mapping,这也是为什么会有 @Entity 这个注解的来源

      • Student
      package com.example.hibernatejpa.entity;
      
      import jakarta.persistence.*;
      
      @Entity
      @Table(name = "student")
      public class Student {
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9

      @Table 指代的则是数据库里 student 这个表

    2. 进行数据映射

        @Entity
        @Table(name = "student")
        public class Student {
              // defined fields
          @Id
          @GeneratedValue(strategy = GenerationType.IDENTITY)
          @Column(name = "Id")
          private int id;
      
          @Column(name = "first_name")
          private String firstName;
      
          @Column(name = "last_name")
          private String lastName;
      
          @Column(name = "email")
          private String email;
      
           public Student() {
           }
      
           public Student(String firstName, String lastName, String email) {
               this.firstName = firstName;
               this.lastName = lastName;
               this.email = email;
           }
        }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27

      这里需要一个无参构造函数让 hibernate 去使用反射创建对应的实例

      这里将表格里有的数据和对象里的属性进行映射,毕竟数据库的结构如下:

      在这里插入图片描述

      @Column 是可选的,如果不提供的话数据库中的名字与 Java 中属性名相同。不过数 DB 的属性名称一般用的是 snake,java 用的是 camel,所以也不太推荐这么做

      另外就是,如果代码要更新(比如说换名称之类的),如果不注意这里没修改的话,有可能项目就跑不了了

      同样,@Table 这个注解也是可选的

      这里从数据库 map 的主键就是 id,@GeneratedValue 也就是主键的生成方式为数据库管理,所以在创建新对象的时候不需要将主键传过去

      GenerationType 是可以 override 的,通过实现 IdentifierGenerator 重写对应的方法即可

    到这一步,ORM 的 mapping 这里就实现了

    接下来就是重写 setter/getter/toString 方法,这里就跳过了

    除了手动操作之外,也可以使用 lombok 去除重复的 setter/getter/无参构造函数

    Reference

    • 比较流行的一些 DB 的 Dialect

      RDBMSDialects
      DB2org.hibernate.dialect.DB2Dialect
      DB2 AS/400org.hibernate.dialect.DB2400Dialect
      DB2 OS390org.hibernate.dialect.DB2390Dialect
      PostgreSQLorg.hibernate.dialect.PostgreSQLDialect
      MySQL5org.hibernate.dialect.MySQL5Dialect
      MySQL5 with InnoDBorg.hibernate.dialect.MySQL5InnoDBDialect
      MySQL with MyISAMorg.hibernate.dialect.MySQLMyISAMDialect
      Oracle (any version)org.hibernate.dialect.OracleDialect
      Oracle 9iorg.hibernate.dialect.Oracle9iDialect
      Sybaseorg.hibernate.dialect.SybaseASE15Dialect
      Microsoft SQL Server 2000org.hibernate.dialect.SQLServerDialect
      Microsoft SQL Server 2008org.hibernate.dialect.SQLServer2008Dialect
      SAP DBorg.hibernate.dialect.SAPDBDialect
      Informixorg.hibernate.dialect.InformixDialect
      HypersonicSQLorg.hibernate.dialect.HSQLDialect
      H2 Databaseorg.hibernate.dialect.H2Dialect
      Ingresorg.hibernate.dialect.IngresDialect
      Progressorg.hibernate.dialect.ProgressDialect
      Mckoi SQLorg.hibernate.dialect.MckoiDialect
      Interbaseorg.hibernate.dialect.InterbaseDialect
      Pointbaseorg.hibernate.dialect.PointbaseDialect
      FrontBaseorg.hibernate.dialect.FrontbaseDialect
      Firebirdorg.hibernate.dialect.FirebirdDialect

      不是非常 up-to-date,MySQL8Dialect 都 deprecated 了,我现在用的 MySQL 版本是 8,不过做一个参考还行

    • Mysql start up issues | ERROR! The server quit without updating PID file

  • 相关阅读:
    超详细的cookie属性HttpOnly和SameSite引起的漏洞解决方案
    一次简单的SQL注入靶场练习
    关于《考研数学高分公式》系列的后续及一点说明
    KT6368A双模蓝牙芯片串口与mcu之间串接的电阻以及电平转换说明
    【kafka】七、kafka数据可靠性保证
    爬虫部署 Gerapy 安装(centos 8)演示
    【图像去噪】基于空间光谱总变化减少高光谱图像的混合噪声(Matlab代码实现)
    Unity Andriod调试
    移动通信网络规划:配套设施要求
    GO语言 | go work 神一般的管理 多个module没烦恼
  • 原文地址:https://blog.csdn.net/weixin_42938619/article/details/133698917