传统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。
相关推荐
worxfr34 分钟前
Go 并发控制:从 Channel 方向约束到实战模式
开发语言·后端·golang
拾陆楼44 分钟前
PT: DMSA辅助调tree报告前后级余量脚本
后端·学习
今天的砖头有点烫手啊1 小时前
接口太慢?Spring Boot 缓存体系 @Cacheable 全链路拆解
spring boot·后端·缓存
雪隐2 小时前
个人电脑玩AI-16让5060 Ti给你打工——MiniMax H3 提速实录:从"泡杯茶等视频"到"视频等你",一张 5060 Ti 的自我修养
前端·人工智能·后端
952362 小时前
Sentinel
java·后端·spring·sentinel·springcloud
名字还没想好☜2 小时前
Go 的 sync.Cond 实战:用条件变量做等待/通知,比忙轮询省 CPU
开发语言·数据库·后端·golang·go
zzzll11113 小时前
Spring Boot 入门指南:从零开始构建微服务
spring boot·后端·微服务
运维行者_3 小时前
企业带宽监控工具实战:网络流量分析与异常排查的5个关键能力
运维·服务器·开发语言·网络·分布式·后端·php
长栎3 小时前
你用了五年的消息队列,不知道它背后站着中介者模式
后端
Gopher_HBo3 小时前
路由注册:RouterGroup(routergroup.go)
后端