七年再回首,从JDBC到ORM

2023-12-20 04:12
文章标签 jdbc orm 七年 再回首

本文主要是介绍七年再回首,从JDBC到ORM,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

初学ORM和JDBC还是2016年的10月15日,在宿舍里偷偷记下了一纸笔记。

转眼七年已过,从来没有手写过JDBC,数据库的连接都是通过框架和连接池就给完成了,ORM的工作框架也都顺手给完成了。

本篇文章就用七年后角度,再次学习JDBC和ORM。

JDBC

JDBC即Java数据库连接,是Java提供的一套连接数据库的接口规范,开发者可以通过模板代码来连接不同的数据库。这里就拿MySQL和oracle来举例,画了一个简单的图。

我们可以通过右边java.sql提供的JDBC流程,只要将对应数据库驱动注册到DriverManager中,就能实现对数据库的连接,然后获取连接对象、执行sql、返回结果集。这些在java.sql包里都提供了对应的类。

建表

安装数据库的文章之前有写过,这里直接建表。

一共三个字段,两个varchar字符串类型,一个int类型,然后插入数据。

代码实现

这里先定义一个和表字段一样的Java类。

这里就以MySQL为例,使用JDBC查询数据库。首先我们要引入MySQL的驱动依赖。

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version>
</dependency>

然后就根据JDBC接口规范开始开发代码。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;public class JdbcDemo {public static void main(String[] args) throws Exception {Class.forName("com.mysql.cj.jdbc.Driver");String url = "jdbc:mysql://175.27.xxx.xxx:3306/test";String user = "root";String password = "xxxxxxx";Connection conn = DriverManager.getConnection(url, user, password);Statement statement =  conn.createStatement();String sql = "select * from people";ResultSet rs = statement.executeQuery(sql);while (rs.next()){// System.out.println(rs.getString(1) + "-" + rs.getInt(2) + "-" + rs.getString(3));People people = new People();people.setName(rs.getString(1));people.setAge(rs.getInt(2));people.setPhone(rs.getString(3));System.out.println(people);}rs.close();statement.close();conn.close();}
}

手动对ResultSet遍历,获取每个字段的值,将每个字段set到新创建的People对象中。这里要注意的是:下标是从1开始的。

运行输出结果:

数据表中的三条数据都被查询到并输出了出来。接下来就从头分析一下JDBC流程。

JDBC流程

1. 加载驱动

JDBC中通过Class.forName反射加载驱动类。com.mysql.cj.jdbc.Driver 是MySQL的驱动类,在MySQL的依赖包里,当没有添加MySQL依赖时,就会报错ClasNotFound的异常。

上图为MySQL驱动类源码,继承NonRegisteringDriver并实现了JDBC的Driver接口,在加载类的同时,也会调用static代码块,调用DriverManger的registerDriver方法,向DriverManger注册此驱动。

registeredDrivers是一个CopyOnWriteArrayList,即线程安全的List,记录着各个Driver的信息,addIfAbsent只有当这个driver不存在时,则会添加进去,保证每个数据库的驱动信息只会加载一次。

2. 数据库连接

DriverManger记录着所有驱动的信息,并通过getConnection() 连接数据库并返回Connection对象。代码如下:

aDriver就是存放在registeredDrivers中的Driver信息,这里指的就是MySQL驱动,然后调用此驱动的connect方法连接数据库,看看NonRegisteringDriver类中connect代码。

里面就是所有通过url、user、password信息连接MySQL数据库的逻辑实现,最后返回一个Connection对象。通过断点可以知道,最后返回的是MySQL驱动的ConnectionImpl类。

所以说,JDBC的DriverManger只是提供了管理Driver以及连接数据库的入口(connect方法),至于连接数据库的细节,需要每个数据库的驱动类自己实现细节,只要最后按照JDBC规范,返回一个Connection即可。

3. 执行查询SQL

使用连接对象createStatement方法创建一个Statement对象,即用来直行SQL的一个对象。通过断点可以看到,从MySQL数据库连接中返回的是MySQL实现的StatementImpl对象。

然后调用executeQuery()来执行查询SQL。

最后返回结果集ResultSet,其实返回的是MySQL驱动中自己实现的ResultSet子类ResultSetInternalMethods

最后我们根据ResultSet提供的next来遍历数据集,通过从1开始的索引来获取每条数据中每个字段,手动赋值给People对象。

总结

至此我们可以知道,JDBC提供的Driver、Connection、Statement和ResultSet都是接口,里面所有方法都需要数据库驱动自己实现,MySQL驱动如此,Oracle驱动亦是如此。

ORM

ORM(Object Relational Mapping),对象关系映射,我理解的是就是JAVA类和数据库中表的映射,类字段和表字段的映射以及字段类型的映射。

上面连接MySQL返回结果集ResultSet之后,需要完成手动遍历、创建People对象、赋值等一系列操作,超级麻烦。所以ORM框架就开始出现了,上面这些操作就完全由框架内部处理。从JavaWeb学的DButils,到SSM框架中的MyBatis等都是ORM框架。

与JDBC相比,我们只需要输入SQL,定义好Java类,ORM框架就自动将数据库中查询到的数据,封装到Java类中返回给我们,然后我们从类对象中get数据字段即可。

DButils

引入依赖:

<dependency><groupId>commons-dbutils</groupId><artifactId>commons-dbutils</artifactId><version>1.8.1</version>
</dependency>

使用DButils完成ORM测试代码。

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.List;public class DBUtilsDemo {public static void main(String[] args) throws Exception {Class.forName("com.mysql.cj.jdbc.Driver");String url = "jdbc:mysql://175.27.xxx.xx:3306/test";String user = "root";String password = "xxxxxx";Connection conn = DriverManager.getConnection(url, user, password);String sql = "select * from people";QueryRunner queryRunner = new QueryRunner();List<People> peoples = queryRunner.query(conn, sql, new BeanListHandler<>(People.class));for (People people : peoples) {System.out.println(people);}}
}

从代码里可以看出,这里不会再返回原始的ResultSet数据集,而是queryRunner.query之后直接返回List,这得益于BeanListHandler的内部逻辑,将每条数据都封装成People对象。

我们来看一下输出结果:

结果和上面JDBC的一样,但是少了很多代码。学过JavaWeb的都知道,DButils会和DataSource一起使用,例如C3P0等,所以在QueryRunner直接传入DataSource即可,而不是一个connection。这样代码又少了很多。

与JDBC对比一下,ORM的作用体现在:

MyBatis

MyBatis更为简单,在Mapper文件中使用注解传入SQL,通过返回值关联Java类,直接调用对应的mapper函数,就能获取对相应的数据,实现ORM。


这个方法就是查询数据库中的building_info表,映射成Java的BuildingDataInfo类,每条数据对应一个BuildingDataInfo对象。

与DButils相比,MyBatis更为简单,不需要传入Handler,不需要传入数据源,只要调用提前定义好的方法,就能获取到ORM后的数据。

结语

上面就是我对JDBC和ORM的理解,理解不足之处请指正,期待共同学习和进步。

这篇关于七年再回首,从JDBC到ORM的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/514731

相关文章

滚雪球学Java(87):Java事务处理:JDBC的ACID属性与实战技巧!真有两下子!

咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE啦,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~ 🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!! 环境说明:Windows 10

Go 在orm中使用反射

作为静态语言,golang 稍显笨拙,还好 go 的标准包reflect(反射)包弥补了这点不足,它提供了一系列强大的 API,能够根据执行过程中对象的类型来改变程序控制流。本文将通过设计并实现一个简易的 mysql orm 来学习它,要求读者了解mysql基本知识,并且跟我一样至少已经接触 golang 两到三个月。 orm 这个概念相信同学们都非常熟悉,尤其是写过rails的同学,对acti

Hibernate框架中,使用JDBC语法

/*** 调用存储过程* * @param PRONAME* @return*/public CallableStatement citePro(final String PRONAME){Session session = getCurrentSession();CallableStatement pro = session.doReturningWork(new ReturningWork<C

jdbc连接数据库使用sid和service_name的区别 ?

问题描述: ORA-12505, TNS:listener does not currently know of SID given in connect descriptor The Connection descriptor used by the client was: 10.12.162.84:1521:xxxx  oracle数据的tnsnames.ora中配置的是:SERVICE

Java项目中,配置打印 JDBC 日志的几种方法

在 IDEA 项目中,如果你想打印 JDBC 日志,可以通过配置日志框架(如 Logback 或 Log4j)来实现。Spring Boot 使用的默认日志框架是 Logback,你可以通过在 application.yml 文件中配置日志级别来打印 JDBC 日志。 方法 1: 使用 application.yml 配置 JDBC 日志 logging:level:# 显示 SQL 语句co

基于shard-jdbc中间件,实现数据分库分表

一、水平分割 1、水平分库 1)、概念: 以字段为依据,按照一定策略,将一个库中的数据拆分到多个库中。 2)、结果 每个库的结构都一样;数据都不一样; 所有库的并集是全量数据; 2、水平分表 1)、概念 以字段为依据,按照一定策略,将一个表中的数据拆分到多个表中。 2)、结果 每个表的结构都一样;数据都不一样; 所有表的并集是全量数据; 二、Shard-jdbc 中间件 1、架构图 2、特点

基于Shard-Jdbc分库分表,数据库扩容方案

一、数据库扩容 1、业务场景 互联网项目中有很多“数据量大,业务复杂度高,需要分库分表”的业务场景。 这样分层的架构 (1)上层是业务层biz,实现业务逻辑封装; (2)中间是服务层service,封装数据访问; (3)下层是数据层db,存储业务数据; 2、扩容场景和问题 当数据量持续新增,面临着这样一些需求,两台数据库无法容纳,需要数据库扩容,这里选择2台—扩容到3台的模式,如下图

Java笔试面试题AI答之JDBC(3)

文章目录 13. 编写JDBC连Oracle的程序?14. 简述JDBC的主要组件有哪些 ?15. JDBC中如何防止SQL注入攻击?1. 使用预处理语句(PreparedStatement)2. 避免在SQL查询中直接拼接用户输入的数据总结 16. JDBC的脏读是什么?哪种数据库隔离级别能防止脏读?脏读(Dirty Read)哪种数据库隔离级别能防止脏读? 17. 简述JDBC ex

第二十二章 rust数据库使用:sea-orm详解

注意 本系列文章已升级、转移至我的自建站点中,本章原文为:rust数据库使用:sea-orm详解 目录 注意一、前言二、项目管理三、迁移文件四、实体文件五、业务使用 一、前言 只要开发稍微大型一点的项目,数据库都是离不开的。 rust目前并没有特别成熟的数据库框架,sea-orm这个框架是我目前所看到的成熟度最高的一个,并且仍在积极开发中。 所以本文将以sea-orm框

JavaBug系列- Failed to load driver class com.mysql.cj.jdbc.Driver in either of HikariConfig class load

JavaBug系列之Mysql驱动问题 Java医生一、关于错误信息二、如何解决问题 Java医生 本系列记录常见Bug,以及诊断过程和原因 Java/一对一零基础辅导/企业项目一对一辅导/日常Bug解决/代码讲解/毕业设计等 V:study_51ctofx 一、关于错误信息 APPLICATION FAILED TO START Description: Fai