JDBC存在什么问题?MyBatis是如何解决的?

文章目录

  • 引言
  • JDBC核心组件
    • 1、DriverManager
    • 2、Connection
    • 3、Statement
    • 4、ResultSet
    • 5、SQLException
  • JDBC存在的问题
    • 1、繁琐的代码编写
    • 2、手动管理资源
    • 3、SQL语句的硬编码
    • 4、缺乏对象映射
    • 5、事务管理复杂
    • 6、缺乏缓存支持
  • MyBatis如何解决这些问题?
    • 1、简化代码编写
    • 2、自动资源管理
    • 3、SQL与代码分离
    • 4、支持对象关系映射(ORM)
    • 5、事务管理的简化
    • 6、缓存支持
  • 总结

引言

JDBC(Java Database Connectivity)是 Java中用于连接和操作数据库的标准API,它提供了一种通用的方式来访问数据库,但在实际应用中,直接使用 JDBC会遇到很多的问题。这篇文章,我将详细探讨 JDBC存在的问题以及 MyBatis是如何解决这些问题的。

JDBC核心组件

JDBC的核心组件包含以下 5个组件:
1、DriverManager
2、Connection
3、Statement
4、ResultSet
5、SQLException

1、DriverManager

DriverManager是JDBC API的核心类之一,用于管理JDBC驱动程序的集合,并为应用程序提供数据库连接。它通过加载适当的数据库驱动程序来建立与数据库的连接。

2、Connection

Connection接口表示与特定数据库的连接。它提供了创建SQL语句、提交和回滚事务、关闭连接等方法。通过Connection,应用程序可以与数据库进行交互。

3、Statement

Statement接口用于执行静态SQL语句并返回其生成的结果。JDBC提供了三种类型的Statement:Statement、PreparedStatement和CallableStatement,分别用于执行简单的SQL语句、预编译的SQL语句和存储过程。

4、ResultSet

ResultSet接口表示数据库查询的结果集。它提供了从结果集中检索数据的方法,并支持迭代结果集中的行。

5、SQLException

SQLException是 JDBC API中用于处理数据库访问错误的异常类。它提供了详细的错误信息,包括错误代码和SQL状态。

JDBC存在的问题

1、繁琐的代码编写

在JDBC中,开发者需要编写大量的代码来处理数据库连接、SQL语句的创建和执行、结果集的处理等。对于每一个数据库操作,通常需要执行一系列标准步骤,包括获取连接、创建语句、执行查询、处理结果集和关闭连接。这种重复的代码入侵性太强,很容易导致代码臃肿、不易维护。

2、手动管理资源

JDBC要求开发者手动管理数据库连接、语句和结果集的关闭。这不仅容易导致资源泄露,而且增加了代码的复杂性和出错的可能性,特别是在异常处理部分,确保所有资源都被正确关闭是一项挑战。

3、SQL语句的硬编码

在JDBC中,SQL语句通常是硬编码在 Java代码中的。这种做法使得 SQL和 Java代码紧密耦合,增加了代码的维护难度。如果数据库表结构发生变化,需要在代码中手动更新SQL语句。

4、缺乏对象映射

JDBC直接处理结果集(ResultSet),开发者需要手动将结果集中的数据映射到 Java对象。这种手动映射不仅繁琐,而且容易出错,尤其是在处理复杂的对象关系时。

5、事务管理复杂

虽然JDBC支持事务管理,但开发者需要手动编写代码来处理事务的开始、提交和回滚。这种手动管理增加了代码的复杂性,特别是在处理多个数据库操作需要在一个事务中完成时。

6、缺乏缓存支持

JDBC本身不提供缓存机制,所有的查询都直接从数据库中读取数据。这可能导致性能问题,特别是在频繁访问相同数据的情况下。

为了更好地展示JDBC存在的问题,我们用一个简单的示例进行说明:假设需要查询一个用户表,并将结果映射到 Java对象中,使用JDBC的代码如下:

public User getUserById(int id) {Connection conn = null;PreparedStatement stmt = null;ResultSet rs = null;User user = null;try {// 1. 加载JDBC驱动程序Class.forName("com.mysql.cj.jdbc.Driver");// 2. 建立数据库连接connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "username", "password");// 3. 创建SQL语句对象String sql = "SELECT id, username, email FROM users WHERE id = ?";stmt = connection.prepareStatement(sql);stmt.setInt(1, id);// 4. 执行SQL语句rs = stmt.executeQuery();// 5. 处理结果集if (rs.next()) {user = new User();user.setId(rs.getInt("id"));user.setUsername(rs.getString("username"));user.setEmail(rs.getString("email"));}} catch (SQLException e) {e.printStackTrace();} finally {try {// 6. 关闭资源if (rs != null) rs.close();if (stmt != null) stmt.close();if (conn != null) conn.close();} catch (SQLException e) {e.printStackTrace();}}return user;
}

在上面这个例子中,管理数据库连接、SQL语句的执行和结果集的处理都需要我们手动来管理,看起来太臃肿,很容易出错。估计大家看到这种代码,肯定要吐槽一番。

既然 JDBC存在这么多问题,那么,MyBatis是如何解决这些问题的呢?

MyBatis如何解决这些问题?

MyBatis 是一个流行的持久层框架,在国内占据了很大一部分市场,它支持定制化SQL、存储过程以及高级映射等功能,大大简化了JDBC的使用,并提供了一些额外的功能来解决上述问题。

MyBatis本质上是一个对 JDBC的封装,它利用JDBC来执行底层的数据库操作。所有 MyBatis的数据库交互最终都是通过 JDBC来实现的。

1、简化代码编写

MyBatis通过 XML文件或注解方式定义 SQL语句,将 SQL从 Java代码中分离出来。开发者不再需要手动编写获取连接、创建语句和处理结果集的代码,MyBatis会自动处理这些细节。

例如,MyBatis提供了自动映射机制,可以将查询结果直接映射到Java对象上,减少了手动映射的代码量。

2、自动资源管理

MyBatis框架自动管理数据库连接的获取和释放,开发者不需要手动关闭连接、语句和结果集。这减少了资源泄露的风险,并简化了代码。

3、SQL与代码分离

MyBatis允许将SQL语句放在XML配置文件中或者使用注解,这样SQL和Java代码就被分离开来。这种分离使得代码变得更加清晰、易于维护。同时,SQL语句的修改不需要重新编译Java代码,只需要修改XML文件即可。

4、支持对象关系映射(ORM)

MyBatis提供了强大的结果映射功能,支持将数据库中的结果集直接映射到复杂的Java对象结构中。这种映射不仅支持简单的属性映射,还支持一对多、多对多等复杂关系的映射。

5、事务管理的简化

MyBatis可以与Spring框架集成,从而利用Spring的声明式事务管理功能。这样,开发者可以通过简单的注解来管理事务,而不需要手动编写事务管理代码。

6、缓存支持

MyBatis内置了一级缓存和二级缓存机制。一级缓存是SqlSession级别的缓存,默认开启,生命周期与SqlSession相同。二级缓存是Mapper级别的缓存,可以通过配置开启。这些缓存机制可以显著提高应用的性能。

为了更好地理解 MyBatis是如何解决JDBC的问题,我们还是通过上面的示例来说明。

首先,我们需要定义一个 XML映射文件(UserMapper.xml):

<mapper namespace="com.example.UserMapper"><select id="getUserById" parameterType="int" resultType="User">SELECT id, username, email FROM users WHERE id = #{id}</select>
</mapper>

然后,我们可以在 Java代码中调用这个映射:

public interface UserMapper {User getUserById(int id);
}// 在服务层调用
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.getUserById(1);

在上面这个例子中,代码职责很清晰,MyBatis自动处理了 SQL的执行和结果集的映射,我们只需要定义 SQL语句和 Java接口即可。

总结

本文,我们分析了 JDBC的核心组件,使用存在的问题以及 Mybatis如何解决这些问题,对于一些出道比较早或者接触过 JDBC老项目的Java程序员来说,对 JDBC的使用可能还有体感。而现在大部分项目,Hibernate和 Mybatis这些对象关系映射(ORM)框架对 JDBC做了很好的抽象和封装,提供了更加面向对象的数据库操作方式。因此,开发者不需要直接处理 JDBC的API,而是直接面向 ORM。

但是,但是,但是,重要的事情说三遍:如果你想成为一个优秀的工程师,理解底层原理是必修课,尽管ORM给我们的开发带来了便捷,但是理解JDBC的原理,可以帮助我们更好地理解 Hibernate和 Mybatis这些优秀的 ORM框架。

编辑:三两肉
来源:猿Java

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/55102.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙开发之ArkUI 界面篇 三十四 容器组件Tabs 自定义TabBar

如果需要修改Tabs的图标和文字之间的距离我们该怎么办呢&#xff1f;好在tabBar是联合类型&#xff0c;提供了自定义tabBar&#xff0c;这里就可以显示特殊图标或者是文字图片&#xff0c;如下图&#xff1a; 这里定义了myBuilder的函数&#xff0c;用了 来修饰&#xff0c;没有…

MongoDB中排序、索引和聚合的详细说明

以下是关于MongoDB中排序、索引和聚合的详细说明&#xff1a; 排序&#xff08;Sort&#xff09; 基本语法 使用db.collection.find().sort({field: direction})方法对查询结果进行排序。其中field是要排序的字段&#xff0c;direction可以是1&#xff08;表示升序&#xff0…

结合大语言模型的机械臂抓取操作学习

一、 大语言模型的机械臂抓取操作关键步骤 介绍如何基于大语言模型实现机械臂在PyBullet环境中的抓取操作&#xff0c;涵盖机器人运动学、坐标系转换、抓取候选位姿生成、开放词汇检测以及大语言模型代码生成等模块。 1. 机器人正逆运动学基本概念 正运动学: 已知机器人的关节…

19 Shell Script awk命令

Shell Script awk命令 一、awk 一&#xff09;awk介绍 ​ awk是一个强大的文本分析工具&#xff0c;相对于grep的查找&#xff0c;sed的编辑&#xff0c;awk在其对数据分析并生成报告时&#xff0c;显得尤为强大。简单来说awk就是把文件逐行的读入&#xff0c;以空格为默认分…

《深度学习》【项目】自然语言处理——情感分析 <上>

目录 一、项目介绍 1、项目任务 2、评论信息内容 3、待思考问题 1&#xff09;目标 2&#xff09;输入字词格式 3&#xff09;每一次传入的词/字的个数是否就是评论的长度 4&#xff09;一条评论如果超过32个词/字怎么处理&#xff1f; 5&#xff09;一条评论如果…

【论文阅读】SRCNN

学习资料 论文题目&#xff1a;Learning a Deep Convolutional Network for Image Super-Resolution&#xff08;学习深度卷积网络用于图像超分辨率&#xff09;论文地址&#xff1a;link.springer.com/content/pdf/10.1007/978-3-319-10593-2_13.pdf代码&#xff1a;作者提出的…

白平衡之乘积通道法

免责声明:本文所提供的信息和内容仅供参考。作者对本文内容的准确性、完整性、及时性或适用性不作任何明示或暗示的保证。在任何情况下,作者不对因使用本文内容而导致的任何直接或间接损失承担责任,包括但不限于数据丢失、业务中断或其他经济损失。 读者在使用本文信息时,应…

zabbix报警设置

文章目录 I 通过脚本媒介,调用钉钉电话API。配置脚本设置脚本媒介II 配置发送邮件的信息案例:配置163邮箱配置接收媒介创建动作知识扩展DING 2.0 发钉钉钉机器人自定义webhookzabbix执行远程命令I 通过脚本媒介,调用钉钉电话API。 zabbix可以通过脚本调用钉钉电话API,需要…

oneAPI学习-使用oneAPI 实现矩阵乘法并分析性能瓶颈

oneAPI学习-使用oneAPI 实现矩阵乘法并分析性能瓶颈 一.相关链接二.oneAPI介绍三.矩阵乘法简介四.环境准备五.获取设备列表六.基础版实现代码解释 七.局部内存实现代码解释 八.性能分析1.运行性能分析2.常见分析类型3.分析结果解读4.优化建议5.清理分析数据 oneAPI学习-使用one…

工程文件参考——STM32+HAL+SPI主从机通讯

文章目录 前言CubeMX设置SPI设置NSS设置 SPI从机代码SPI主机代码 前言 关于如何简单的写一个稳定的SPI主从机通讯&#xff0c;思路很简单 1、SPI高速传输的时候很容易出现错位之类的问题&#xff0c;CRC的校验首先是必要的。在STM32中SPI使用DMA通讯可以自动执行CRC的校验&…

Linux——Harbor(容器镜像 管理项目)

镜像拉取存在一定的问题&#xff0c;出现原因在于&#xff1a; 使用官方公共仓库中的镜像。 拉取的镜像&#xff0c;主要保存在一下仓库中&#xff1a; docker.io //Docker hub 最大的官方维护的公共镜像仓库&#xff0c;一般都会提供所有项目的最新版镜像&#xff0c;镜像…

springboot 整合 快手 移动应用 授权 发布视频 小黄车

前言&#xff1a; 因快手文档混乱&#xff0c;官方社区技术交流仍有很多未解之谜&#xff0c;下面3种文档的定义先区分。 代码中的JSON相关工具均用hutool工具包 1.快手 移动双端 原生SDK 文档https://mp.kuaishou.com/platformDocs/develop/mobile-app/ios.html 2.快手 Api 开…

物联网智能项目(含案例说明)

物联网&#xff08;Internet of Things&#xff0c;简称IoT&#xff09;智能项目是指利用物联网技术将各种物理设备、传感器、软件、网络等连接起来&#xff0c;实现设备之间的互联互通&#xff0c;并通过数据采集、传输、处理和分析&#xff0c;实现智能化管理和控制的项目。以…

LINUX---shell变量(或bash变量)和环境变量的区别

Shell 变量是特定于当前 shell 会话的变量。 作用范围&#xff1a;仅在当前 shell 会话中有效。如果你打开了多个终端窗口&#xff0c;每个窗口都有自己的一组 shell 变量&#xff0c;彼此独立。 生命周期&#xff1a;随着 shell 会话的结束而消失&#xff0c;不会传递给其他 …

Qt与下位机通信时,如何等待下位机回复和超时处理

在C或Qt中实现与下位机&#xff08;例如嵌入式设备、传感器等&#xff09;的通信&#xff0c;并且需要等待对方回复&#xff0c;如果几秒后没有收到回复则执行下一步动作&#xff0c;可以使用多种方法来实现这种超时机制。以下是几种常见的实现方式&#xff1a; 1. 使用 QTime…

springboot整合lombok

只需要引入lombok依赖 <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version></dependency> 然后application.yml配置文件中加上 logging: level: …

【Codeforces】CF 1082 G

Petya and Graph #网络流 #图论 #最小割 题目描述 Petya has a simple graph (that is, a graph without loops or multiple edges) consisting of n n n vertices and m m m edges. The weight of the i i i-th vertex is a i a_i ai​. The weight of the i i i-th…

Qt入门教程:创建我的第一个小程序

本章教程&#xff0c;主要介绍如何编写一个简单的QT小程序。主要是介绍创建项目的过程。 一、打开QT软件编辑器 这里使用的是QT5.14.2版本的&#xff0c;安装教程参考以往教程&#xff1a;https://blog.csdn.net/qq_19309473/article/details/142907096 二、创建项目 到这里&am…

【Docker】03-自制镜像

1. 自制镜像 2. Dockerfile # 基础镜像 FROM openjdk:11.0-jre-buster # 设定时区 ENV TZAsia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone # 拷贝jar包 COPY docker-demo.jar /app.jar # 入口 ENTRYPOINT ["ja…

Flutter应用解析(一)

1、创建项目 1.1 新建 1.2 选择Flutter SDK的位置 1.3 项目名称 英文单词加下划线起名规范&#xff0c;其他默认即可。 1.4 点击运行 发生报错显示我们的JAVA版本不符合 1.5 更改版本设置 1.6 再次启动项目 2、分析页面代码 以下是lib/main.dart的源代码&#xff08;为了阅…