[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 里面配置,我配置的内容如下:

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

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

补充一下: 我创建了对应的用户和密码,没有创建的话,使用默认的用户名和密码 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)就会启动失败,解决方案是彻底删除残留的文件夹,再重新安装就好了

    我用的脚本为:

    bash 复制代码
    ❯ brew uninstall mysql
    ❯ rm -Rf /usr/local/var/mysql
    ❯ brew install mysql
    ❯ mysql.server start

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

项目配置

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

java 复制代码
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");
	}
}

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

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

properties 复制代码
spring.main.banner-mode=off
logging.level.root=warn

修改了之后,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
    java 复制代码
    package com.example.hibernatejpa.entity;
    
    import jakarta.persistence.*;
    
    @Entity
    @Table(name = "student")
    public class Student {
    }

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

  2. 进行数据映射

    java 复制代码
      @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;
         }
      }

    这里需要一个无参构造函数让 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

    RDBMS Dialects
    DB2 org.hibernate.dialect.DB2Dialect
    DB2 AS/400 org.hibernate.dialect.DB2400Dialect
    DB2 OS390 org.hibernate.dialect.DB2390Dialect
    PostgreSQL org.hibernate.dialect.PostgreSQLDialect
    MySQL5 org.hibernate.dialect.MySQL5Dialect
    MySQL5 with InnoDB org.hibernate.dialect.MySQL5InnoDBDialect
    MySQL with MyISAM org.hibernate.dialect.MySQLMyISAMDialect
    Oracle (any version) org.hibernate.dialect.OracleDialect
    Oracle 9i org.hibernate.dialect.Oracle9iDialect
    Sybase org.hibernate.dialect.SybaseASE15Dialect
    Microsoft SQL Server 2000 org.hibernate.dialect.SQLServerDialect
    Microsoft SQL Server 2008 org.hibernate.dialect.SQLServer2008Dialect
    SAP DB org.hibernate.dialect.SAPDBDialect
    Informix org.hibernate.dialect.InformixDialect
    HypersonicSQL org.hibernate.dialect.HSQLDialect
    H2 Database org.hibernate.dialect.H2Dialect
    Ingres org.hibernate.dialect.IngresDialect
    Progress org.hibernate.dialect.ProgressDialect
    Mckoi SQL org.hibernate.dialect.MckoiDialect
    Interbase org.hibernate.dialect.InterbaseDialect
    Pointbase org.hibernate.dialect.PointbaseDialect
    FrontBase org.hibernate.dialect.FrontbaseDialect
    Firebird org.hibernate.dialect.FirebirdDialect

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

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

相关推荐
JH307311 分钟前
Oracle与MySQL中CONCAT()函数的使用差异
数据库·mysql·oracle
码蜂窝编程官方2 小时前
【含开题报告+文档+PPT+源码】基于SpringBoot+Vue的虎鲸旅游攻略网的设计与实现
java·vue.js·spring boot·后端·spring·旅游
AuroraI'ncoding3 小时前
时间请求参数、响应
java·后端·spring
斗-匕3 小时前
MySQL 三大日志详解
数据库·mysql·oracle
计算机毕设指导65 小时前
基于 SpringBoot 的作业管理系统【附源码】
java·vue.js·spring boot·后端·mysql·spring·intellij-idea
ExiFengs6 小时前
实际项目Java1.8流处理, Optional常见用法
java·开发语言·spring
瓜牛_gn7 小时前
依赖注入注解
java·后端·spring
王小小鸭7 小时前
【开发小技巧11】用经典报表实现badge list效果,根据回显内容用颜色加以区分
oracle·oracle apex
大白要努力!7 小时前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle
一元咖啡8 小时前
SpringCloud Gateway转发请求到同一个服务的不同端口
spring·spring cloud·gateway