Java JPA & ORM框架

一些概念:JDBC & PJA & ORM

JDBC (Java Database Connectivity) API,即Java数据库编程接口,是一组标准的Java语言中的接口和类,使用这些接口和类,Java客户端程序可以访问各种不同类型的数据库。


JPA 全称为Java Persistence API ,Java持久化API是Sun公司在Java EE 5规范中提出的Java持久化接口。JPA吸取了目前Java持久化技术的优点,旨在规范、简化Java对象的持久化工作。使用JPA持久化对象,并不是依赖于某一个ORM框架。
JPA规范本质上就是一种ORM规范,注意不是ORM框架——因为JPA并未提供ORM实现,它只是制订了一些规范,提供了一些编程的API接口,但具体实现则由服务厂商来提供实现,JBoss应用服务器底层就以Hibernate作为JPA的实现。
虽然 ORM 框架都实现了 JPA 规范,但是在不同 ORM 框架之间切换是需要编写的代码有一些差异,而通过使用 Spring Data Jpa 能够方便大家在不同的 ORM 框架中间进行切换而不要更改代码。并且 Spring Data Jpa 对 Repository 层封装的很好,可以省去不少的麻烦。


ORM :对象关系映射(Object Relational Mapping,简称 ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM 是通过使用描述对象和数据库之间映射的元数据,将 java 程序中的对象自动持久化到关系数据库中。

从 JDBC 到 ORM

JDBC 规范对与数据库的交互做了如下抽象:用 Connection 代表和数据库的连接,用 Statement 执行 SQL,用 ResultSet 表示 SQL 返回的结果,提供了对数据的遍历。从 Connection 可以创建 Statement,Statement 执行查询得到 ResultSet。

Connection、Statement、ResultSet 都是接口,具体实现由各个数据库提供商提供。可以通过 JDBC统一的接口,访问多种类型的数据库,可随便切换数据库。

下面是一个例子:

Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//1. 加载驱动
Class.forName("com.mysql.jdbc.Driver");

//2. 获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/dropnotes?serverTimezone=UTC", "user", "pwd");

//3. 创建 PreparedStatement
ps = conn.prepareStatement("select * from notes");

//4. 执行sql
rs = ps.executeQuery();

//5. 遍历结果集
while(rs.next()) {
System.out.println(rs.getString(2));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
rs.close();
ps.close();
conn.close();
}
catch (SQLException e) {
e.printStackTrace();
}
}

JDBC1 提供了 DriverManager 用于加载数据库驱动 & 获取 connection ,但这种方式显然不方便,需要自己管理 connection ,频繁建立 & 释放 connection 性能也不高。

DriverManager 中使用了 SPI 模式来加载数据库 Driver Jar 包 @ref:: Java常用机制 - SPI机制详解 | Java 全栈知识体系

在 JDBC2 中支持了 DataSource 的方式,DataSource 包含连接池和连接池管理2个部分,习惯上称为 #数据库连接池 。在初始化的时候,建立一些 connection 对象并存储在缓存中,当需要访问数据库时,从连接池中取出一个已建立的空闲 connection 对象。

DataSource 也只是一个规范,具体的实现有 dbcp、c3p0、druid ,使用 c3p0 连接池的代码如下:

public static ComboPooledDataSource dataSource = new ComboPooledDataSource();

public static void dataSource(){
try {
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test?serverTimezone=UTC");
dataSource.setUser("root");
dataSource.setPassword("123456");
dataSource.setInitialPoolSize(3);
dataSource.setMaxPoolSize(10);
dataSource.setMinPoolSize(3);
dataSource.setAcquireIncrement(3);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
}

public static Connection conn() {
Connection conn = null;
dataSource();
try {
conn = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}

使用了连接池后,无需手动管理 connection 释放,方便了很多,但此时还是需要手动写 Statement 和 ResultSet 的代码。

这时候就需要使用 ORM(对象关系映射),主要解决数据库数据和 POJO 对象的相互映射,就不需要手动写 SQL 了

选型对比

Spring JPA - MyBatis

Spring Data JPA or Mybatis?

Jpa(Java Persistence API)是 sun 官方提出的 java 持久化规范。它为 java 开发人员提供了一种对象/关联映射工具,来管理 java 应用中的关系数据。它的出现主要是为了简化现有的持久化开发工作和整合 ORM 技术,结束现在 hibernate、toplink、jdo 等 ORM 框架各自为营的局面。

值得注意的是,Jpa 是在充分吸收了现有 ORM 框架的基础上发展而来的,具有易于使用,伸缩性强等优点。从目前的开发社区的反应上看,Jpa 受到了极大的支持和赞扬,其中就包括了 spring 和 EJB 的开发团队。

  • Spring Data Jpa 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套 Jpa 应用框架,可使开发者用极简的代码即可实现对数据库的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展

  • MyBatis 本是 apache 的一个开源项目 iBatis, 2010年这个项目由 apache software foundation 迁移到了 google code,并且改名为 MyBatis 。Mybatis:着力于 POJO 与 SQL 之间的映射关系

Spring Data JPA 默认使用 hibernate 作为 ORM。我们再看看 hibernate 的官方概念,Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,它将 POJO 与数据库表建立映射关系,是一个全自动的 orm 框架,hibernate 可以自动生成 SQL 语句

@ref: SpringBoot开发使用Mybatis还是Spring Data JPA?? - 知乎


使用 Spring Data Jpa 仅需要定义接口,并继承 JpaRepository 接口,不需要编写实现类,也不需要编写 XML 映射文件。Spring Data Jpa 默认提供简单的 CRUD 方法,并支持自动根据方法名生成 SQL,提供注解方式动态生成 SQL,也支持分页、排序。

个人更喜欢在分布式微服务项目中使用 Spring Data Jpa,特别是使用领域驱动设计架构设计的项目,而在管理后台项目使用 Mybatis。

因为管理后台需要更灵活的查询支持,经常写些复杂的 SQL,在这方面 Jpa 显得较弱势,而分布式微服务项目实现业务的核心逻辑,只需要用到简单的数据查询、删增改,因此较适合使用 Jpa。

@ref: Mybatis与Spring Data Jpa怎么选? - 掘金

Hibernate - MyBatis

Hibernate 和 Mybatis 都是 ORM 持久层框架

Hibernate 提供的是一种全表映射的模型,对 JDBC 的封装程度比较高。但 Hibernate 也有不少缺点:

  • 全表映射带来的不便,比如更新时需要发送所有的字段;
  • 无法根据不同的条件组装不同的SQL;
  • 对多表关联和复杂SQL查询支持较差,需要自己写SQL,返回后,需要自己将数据组装为POJO;
  • 不能有效支持存储过程;
  • 虽然有HQL,但性能较差,大型互联网系统往往需要优化SQL,而Hibernate做不到。

大型互联网环境中,灵活、SQL 优化,减少数据的传递是最基本的优化方法,Hibernate 无法满足要求,而 MyBatis 是一个半自动映射的框架,提供了更灵活、方便的方式。

MyBatis需要手工匹配提供POJO、SQL和映射关系,而全表映射的Hibernate只需要提供POJO和映射关系。

Spring Data JPA

MyBatis

在 Spring 项目中引入 MyBatis 支持 @link JavaEE.SpringMVC
主要是定义 SqlSessionFactory、DataSource 和 Mapper。

Mybatis 四大核心类:

  • SqlSessionFactoryBuilder:会根据配置信息或代码来生成 SqlSessionFactory;
  • SqlSessionFactory:依靠工厂来生成SqlSession;
  • SqlSession:是一个既可以发送SQL去执行并返回结果,也可以获取Mapper的接口;
  • SQL Mapper:是MyBatis新设计的组件,由一个Java接口和XML文件构成,需要给出对应的SQL和映射规则。它负责发送SQL去执行,并返回结果。

Hibernate