传统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。
相关推荐
青云计划9 小时前
知光项目知文发布模块
java·后端·spring·mybatis
Victor3569 小时前
MongoDB(9)什么是MongoDB的副本集(Replica Set)?
后端
Victor3569 小时前
MongoDB(8)什么是聚合(Aggregation)?
后端
yeyeye11110 小时前
Spring Cloud Data Flow 简介
后端·spring·spring cloud
Tony Bai11 小时前
告别 Flaky Tests:Go 官方拟引入 testing/nettest,重塑内存网络测试标准
开发语言·网络·后端·golang·php
+VX:Fegn089511 小时前
计算机毕业设计|基于springboot + vue鲜花商城系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
程序猿阿伟11 小时前
《GraphQL批处理与全局缓存共享的底层逻辑》
后端·缓存·graphql
小小张说故事11 小时前
SQLAlchemy 技术入门指南
后端·python
识君啊12 小时前
SpringBoot 事务管理解析 - @Transactional 的正确用法与常见坑
java·数据库·spring boot·后端
想用offer打牌13 小时前
MCP (Model Context Protocol) 技术理解 - 第五篇
人工智能·后端·mcp