前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >七年再回首,从JDBC到ORM

七年再回首,从JDBC到ORM

原创
作者头像
叫我阿柒啊
修改2023-12-15 09:59:09
2190
修改2023-12-15 09:59:09
举报
文章被收录于专栏:Java放弃之路入门到放弃之路

前言

初学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的驱动依赖。

代码语言:html
复制
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.27</version>
</dependency>

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

代码语言:java
复制
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

引入依赖:

代码语言:html
复制
<dependency>
    <groupId>commons-dbutils</groupId>
    <artifactId>commons-dbutils</artifactId>
    <version>1.8.1</version>
</dependency>

使用DButils完成ORM测试代码。

代码语言:java
复制
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<People>,这得益于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的理解,理解不足之处请指正,期待共同学习和进步。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • JDBC
    • 建表
      • 代码实现
        • JDBC流程
          • 1. 加载驱动
          • 2. 数据库连接
          • 3. 执行查询SQL
        • 总结
        • ORM
          • DButils
            • MyBatis
            • 结语
            相关产品与服务
            数据库
            云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档