传统JDBC的缺点

1. 繁琐的样本代码

每次执行一条sql,无论sql简单还复杂,都需要:加载驱动、创建连接、遍历结果集、关闭资源等流程。这会导致核心逻辑淹没在大量的支撑代码当中。

示例:比如即使是查询一个用户名,也要写如下的代码:

ini 复制代码
public static void main(String[] args) throws ClassNotFoundException {
    Class.forName("com.mysql.jdbc.Driver");
    Connection connection = null;
    PreparedStatement preparedStatement = null;
    ResultSet resultSet = null;
    try {
        connection = DriverManager.getConnection("jdbc:mysql://192.168.1.1:3306/ruoyi?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true&allowMultiQueries=true&useInformationSchema=true", "root", "123456");
        preparedStatement = connection.prepareStatement("select user_name from sys_user where user_id=1");
        resultSet = preparedStatement.executeQuery();
        while (resultSet.next()) {
            System.out.println(resultSet.getString("user_name"));
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }   finally {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (preparedStatement != null) {
                preparedStatement.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2. 资源释放容易泄露

JDBC要求开发者手动关闭ResultSet、PreparedStatement、Connection资源。在复杂的逻辑中(比如多重嵌套的if-else),容易遗漏某个资源的关闭,导致数据库连接池用尽,最终程序崩溃。

3. 硬编码SQL导致代码维护困难

JDBC将sql直接写在java类中,当业务变更导致表结构或查询语句变更时,需要改java代码并重编译整个项目。同时这种字符串拼接的方式,开发体验非常差,非常容易将sql拼写错误。

4. 参数设置及其不灵活

JDBC变量的占位符是?,开发人员必须手动通过索引来设置参数(ps.setLong(0,1))。当sql

参数很多时,数清楚每个占位符对应的变量非常麻烦。

vbscript 复制代码
// 这种代码极其容易把位置指错
ps.setString(1, user.getName());
ps.setInt(2, user.getAge());
ps.setString(3, user.getEmail());
// ... 想象一下有 30 个参数的情况

5. 结果集映射手动转换

JDBC返回的结果集是ResultSet对象。开发人员需要遍历结果集,并一个一个字段的取数据,组装到POJO对象中。

ini 复制代码
public class JdbcUtils {

    @Data
    static class User {
        private Long userId;
        private String userName;
        private String password;
        private Integer age;
    }

    public static void main(String[] args) throws ClassNotFoundException {
        Class.forName("com.mysql.jdbc.Driver");
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            connection = DriverManager.getConnection("jdbc:mysql://192.168.1.1:3306/ruoyi?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true&allowMultiQueries=true&useInformationSchema=true", "root", "123456");
            preparedStatement = connection.prepareStatement("select * from sys_user where user_id=?");
            preparedStatement.setLong(1, 1);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                User user = new User();
                user.setUserId(resultSet.getLong("user_id"));
                user.setUserName(resultSet.getString("user_name"));
                user.setPassword(resultSet.getString("password"));
                user.setAge(resultSet.getInt("age"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }   finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

6. 异常处理太笼统

JDBC抛出的异常基本都是SQLException,无论是语法错误、连接超时、违反唯一键约束,还是数据库挂了,抛出的都是同一个异常。很难通过这个异常定位出更具体的问题。

7. 缺乏事务管理的便捷性

在 JDBC 中处理事务需要手动调用 conn.setAutoCommit(false)conn.commit() / conn.rollback()。当涉及跨多个 Service 调用的复杂事务时,手动传递 Connection 对象会让代码耦合度爆炸。

为了解决这些痛点,业界提供了一些解决方案:

  • apache DbUtils/Spring JdbcTemplate:主要解决样板代码和资源关闭问题
  • Mybatis:解决了SQL硬编码和结果集映射的问题
  • Hibernate、spring data jpa:通过ORM对象映射,让我们彻底摆脱编写简单SQL。
相关推荐
JaguarJack4 小时前
PHP 的异步编程 该怎么选择
后端·php·服务端
风象南4 小时前
AI 写代码效果差?大多数人第一步就错了
人工智能·后端
BingoGo4 小时前
PHP 的异步编程 该怎么选择
后端·php
焗猪扒饭14 小时前
redis stream用作消息队列极速入门
redis·后端·go
树獭非懒14 小时前
AI大模型小白手册|Embedding 与向量数据库
后端·python·llm
IT_陈寒17 小时前
SpringBoot实战:5个让你的API性能翻倍的隐藏技巧
前端·人工智能·后端
梦想很大很大18 小时前
拒绝“盲猜式”调优:在 Go Gin 项目中落地 OpenTelemetry 链路追踪
运维·后端·go
唐叔在学习18 小时前
就算没有服务器,我照样能够同步数据
后端·python·程序员
用户685453759776919 小时前
同步成本换并行度:多线程、协程、分片、MapReduce 怎么选才不踩坑
后端