09_database_01_introduction

第七十六章 数据库应用程序 (Database Applications)

1 简介

数据库应用程序(Database Application)是Java生态系统中重要的一个应用领域。使用数据库技术能够帮助开发人员构建一个完整的、一致的、安全的数据环境。在现代各种应用系统中,数据库仍然起着重要的作用。

由于Java语言提供的丰富特性,各种基于Java语言的数据库开发技术不断涌现出来。除了最基本的JDBC (Java Database Connectivity)之外,Java生态环境中还出现了JPA (Java Persistence API)、ORM (Object-Relational Mapping)等技术;新的数据库框架和代码库也在不断的迭代更新,其流行的代码库有HibernateSpring DataEclipseLinkApache OpenJPAMyBatisQueryDSLjOOQ等,它们有着不同的侧重点和特色。我们将会在接下来的章节中逐一介绍它们。

2 JDBC (Java Database Connectivity)

在开始之前,我们先快速的介绍一些术语,以免一起混淆。站在数据库的角度看,数据库自身被成为数据库服务器(Database Server),而使用数据库的软件或者应用被成为数据库客户端(Database Client)。数据库客户端又被成为数据库应用程序(Database Application)。例如:我们将要介绍的,使用Java语言编写的程序、软件都属于数据库应用程序或者数据库客户端。

数据库工作于客户端-服务器模型(Client-Server Model)下。一台数据库服务器可同时服务于多个数据库客户端。这些客户端可同时与该台数据库服务器建立连接,并执行查询或者其他数据操作。同理,一个数据库客户端也可以同时连接多台数据库服务器。

每台数据库服务器都会设计一套客户端-服务器的通信协议(Client-Server Communication Protocol)。但凡实现了该通信协议的客户端都能与该数据库建立连接,执行操作。因此,数据库客户端可由任何编程语言实现。

在Java开发环境中,早在1997年,Java的设计者推出了一套Java应用程序与数据库服务器的接口JDBC (Java Database Connectivity)。该接口向Java应用程序提供了一套统一的数据操作接口,无论该程序使用的是哪个数据库,它都可以使用相同的接口完成数据操作。这套接口定义在Java标准库的java.sql包中,工作于数据库客户端。随后,Java语言进而推出了扩展包javax.sql,用于增强数据库服务器端的数据源(Server-side Data Source)的处理。

为了使得Java应用程序能够与数据库服务器建立连接,正常通信,Java应用程序(客户端)还需要数据库驱动程序(Database Driver),以适配不同的数据库通信协议。如下图所示,Java应用程序可通过JDBC接口访问PostgreSQL、MySQL、或者Oracle数据库服务器。数据库驱动程序实现了各个数据库的通信协议。

3 JPA (Java Persistence API)

JPA是一套Java对象(数据)的持久化接口(Persistence API)。数据持久化(Data Persistence)技术是指将数据保存在持久化设备(例如:硬盘)中的技术。当系统发生错误重启后,数据仍然持久有效,能够从持久化设备中恢复。那么,简而言之,Java持久化接口是一套用于将Java对象中的数据保存入持久化设备的接口。JPA的重点在于持久化的过程与操作;它与具体的持久化技术是相互独立的。换句话说,JPA接口能够与任何数据持久化技术结合使用;数据能够通过文件系统持久化在硬盘上,也可以持久化在关系型数据库或者NoSQL数据库(例如:Redis数据库)中,或者备份到远程服务器上。

JDBC和JPA有着许多相同之处。

  1. JDBC与JPA都是一种标准(Specification)。JDBC标准化了Java应用程序与数据库服务器的通信方式;JPA标准化了Java数据持久化方式。
  2. JDBC与JPA都定义了一套接口。各个数据库的驱动程序是JDBC接口的实现(An implementation of JDBC Interface)。JPA也有着许多实现,例如HibernateEclipseLinkApache OpenJPA
  3. JDBC和JPA操作的对象都是数据。

JDBC和JPA也有着许多不同之处。

  1. JDBC侧重于Java应用程序与数据库之间的连接和操作。虽然,JDBC并不限制Java应用程序仅能与关系型数据库通信;从接口上看,JDBC也能用于其他数据库,但是,至今为止,尚未出现使用JDBC连接NoSQL数据库的趋势。JPA则可以与任何持久化技术结合使用。
  2. JDBC是较为底层的接口(Low-level Interface),它需要处理许多与数据库相关的实现细节。而JPA是较为高层的接口(High Level Interface)。
  3. JDBC详细描述了数据操作和使用的细节。例如,Java开发人员需要具备如何使用SQL语言的知识。而JPA则侧重于Java对象;所有的操作都是基于对象的操作。一个具体的例子是当使用JDBC查询一个对象时,开发人员需要创建Select语言,并执行查询。但是在使用JPA时,开发人员只需知道类名称和键值即可创建相应的对象。

4 ORM (Object Relational Mapping)

ORM是一种将对象映射到关系型数据模型的方法。ORM是一种高层的抽象(High-Level Abstraction),它可以在JDBC接口上实现,也可以通过JPA接口实现。ORM是一种更容易被Java开发人员理解和接受的方法。因为在Java程序里,开发人员只需要理解数据结构、数据类型、以及它们之间的关系即可。开发人员可能并不在意数据如何从数据库中读取出来。另外一个原因可能是Java开发人员更擅长于编写Java代码,而非SQL语句(如果是使用关系型数据库的话)。

4 JPA框架介绍

在大致了解了JDBC和JPA之后,我们再来简单介绍一下目前Java生态系统中流行的几种框架和代码库。

Hibernate是一款开源的ORM框架。它能将面向对象模型中的数据(Data in Object-Oriented Model)映射到关系型模型中(Relational Model)。Hibernate是目前最为流行的一个JPA的实现(An implementation of JPA)。使用Hibernate有诸多好处。其一,Hibernate是一个独立的框架,它能与绝大多数流行的数据库一起工作。其二,Hibernate提供自行设计的HQL(Hibernate Query Language)。HQL被称为SQL的面向对象版本(An Object-Oriented Version of SQL),因为HQL是基于面向对象的设计理念的;HQL不依赖于任何数据库的实现细节,因此,它能用于任何数据库之上。其三,Hibernate框架内置了缓存机制,加快数据查询等操作。其四,Hibernate还使用了OGM(Object-Grid Mapper)技术支持NoSQL数据库,例如(InfinispanMongoDBNeo4j)。

Spring DataSpring大家庭中的一员。Spring框架自成体系;Spring Data是Spring中的一个子模块。而在Spring Data中,包含有Spring Data JDBC、Spring Data JPA、和针对不同NoSQL数据库的子模块(例如:Spring Data Redis,Spring Data MongoDB等)。

Spring Data将这些模块整合在一起,向上层的应用程序提供统一的接口。因此,在应用程序中,开发人员能够使用相同的代码来管理和使用不同数据库中的数据。Spring Data遵从Spring框架的设计理念,因此,Spring Data能和其他Spring模块较好的融合在一起,协同工作。

EclipseLink是由Eclipse基金会(Eclipse Foundation)开发的开源的项目。EclipseLink是JPA标准的参考实现版本(The Reference Implementation of JPA)。EclipseLink侧重于三个方向上的发展。其一,使用JPA/ORM技术,将数据持久化在关系型数据库中;其二,使用MOXy技术,实现对象与XML文档/JSON文档之间的映射与相互转换;其三,开发DBWS技术,实现由Web Service来访问关系型数据库。因此,当开发人员需要通过使用Web Service来提供数据服务时,EclipseLink可能会是一个不错的选择。

Apache OpenJPA是由Apache软件基金会(Apache Software Foundation)开发的开源项目。在实现JPA接口的基础上,OpenJPA还设计了JPQL(Java Persistence Query Language)。JPQL的优势在于开发人员能够运用面向对象的概念来构造数据库查询语句,避免了开发人员学习和使用SQL语言的具体细节。

MyBatis也是一个流行的Java持久化框架;MyBatis支持ORM技术,但是MyBatis并不支持JPA标准。所以,MyBatis并不是一个JPA框架或者实现。与上述JPA框架不同的是,MyBatis并不隐藏SQL语言;反而MyBatis认为使用SQL语句能够释放SQL以及数据库的最大潜能。因此,MyBatis将对象映射到SQL语句上,而不是数据库中的表上。因此,在MyBatis中,开发人员可以使用几乎所有数据库的特性,例如:试图(View),存储过程(Stored Procedures)等特性。

在实际项目中,我们应该如何选择JPA框架呢?

  1. Hibernate是一个非常成熟的框架,它的第一个版本发布于2001年。在此之后,Hibernate还在不断的完善和推出新的特性。市场上有很多Hibernate的书籍、文档和服务。Hibernate能很好的支持ORM,开发人员无需在编写SQL语句来插入、删除、或者更新一个持久化对象。
  2. Spring Data是Spring大家庭中的一员。如果在项目中已经或者计划使用Spring的其他模块的化,那么,Spring Data应该是最好的选择。诚然,学习Spring可能会更困难一些,毕竟Spring Data依赖于整个Spring框架的基础,而其他JPA框架相对独立一些。但是,一旦用上了Spring之后,学习其他Spring模块会非常快,因为它们运用了相同的设计思想与接口。
  3. EclipseLink是JPA标准的参考实现版本。如果比较JPA标准实现的完整性和兼容性方面,EclipseLink一定是最好的,因为它是参考实现版本。如果在实际项目中特别看重JPA兼容性的化,EclilpseLink是最好的选择。
  4. OpenJPA也是一个高质量的JPA框架。虽然OpenJPA的相关文档和社区并没有Hibernate那样成熟,但是,一些开发人员仍然喜欢使用OpenJPA,因为OpenJPA在一些应用场景下性能更好,使用更方便。
  5. MyBatis的特点鲜明。如果开发人员希望使用数据库中的具体特性,而且不希望直接使用SQL语言的话,MyBatis是一个不错的选择。

5 与数据持久化相关的框架介绍

QueryDSL是一款帮助开发人员创建类SQL查询语句的框架。它支持生成SQL查询语句、JPA查询语句、MongoDB查询语句等多种不同的使用场景。生成查询语句(Queries)是QueryDSL框架的一个特色,但是,QueryDSL还可以用于生成插入(Insert)、删除(Delete)、和更新(Update)等其他语句。QueryDSL的另一个特色是类型安全(Type-Safe)。QueryDSL利用了Java语言泛型编程的特性来检查参数类型,避免程序出现类型不匹配或者安全问题。

jOOQ也是一款帮助开发人员创建SQL语句的框架。jOOQ的全名为jOOQ Object Oriented Querying,是一个首字母递归的名字。jOOQ也能为开发人员提供类型安全的SQL语句,但是,jOOQ的设计理念完全不同。jOOQ推崇先设计数据模型,再编写数据处理的逻辑的开发理念。这个理念常常被称为Database First, Then Java Classes。

jOOQ的工作原理为,开发人员首先建立数据模型,并设置好数据库中的内容。然后,使用jOOQ工具读取数据库中的内容,并生成相应的Java类。实际上,这些生成的Java类体现了数据库中的数据结构和关系。最后,开发人员使用这些生成的类来创建SQL语句。实现数据操作。

那么,我们应该如何选择QueryDSL或者jOOQ呢?其实,QueryDSL与jOOQ各有优势。QueryDSL与jOOQ之间的比较也是数据库为先的设计理念(Database First Design)与代码为先的设计理念(Code First Design)之间的比较。当面对一个新的需求时,如果使用QueryDSL的话,开发人员需要自行修改数据库的内容和相应的代码调整。如果使用的是jOOQ,在修改完数据库之后,开发人员需要使用jOOQ重新生成新的类,并相应调整数据处理逻辑。两者之间的选择需视实际情况而定。根据以往的经验来看,更多的开发人员偏爱于在JPA的环境下使用QueryDSL;而更多开发人员则在SQL的环境下选择jOOQ。

6 小结

本章简单介绍了Java持久化技术中的JDBC标准和JPA标准,并比较了几款流行的Java框架。Hibernate是一款"历史悠久"的Java持久化框架。但是,在Spring框架面世之后,Spring逐渐的受到了更多开发者的青睐。另一方面,QueryDSL和jOOQ也是比较受欢迎的框架,因为在有些项目中,出于各种原因,开发人员不需要一个完整的JPA解决方案,他们只需要一个轻量级的、可用于生成查询语句的代码库。因此,我们在本章中将他们全部涵盖进来,我们将会在接下来的章节中做一一介绍。

上一章
下一章

注册用户登陆后可留言

Copyright  2019 Little Waterdrop, LLC. All Rights Reserved.