apache DbUtils 组件核心原理与应用

2024-04-30 10:04

本文主要是介绍apache DbUtils 组件核心原理与应用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Apache DbUtils 是一个 Apache 组织提供的开源 JDBC 工具类库,它对 JDBC 进行了简单封装,使得数据库操作更加简洁和安全。DbUtils 的核心组件主要包括 QueryRunner、ResultSetHandler 和 RowProcessor,下面将对这些组件进行介绍,并结合源代码分析其工作原理。

核心组件介绍与原理

  1. QueryRunner:
  • QueryRunner 是执行数据库查询、更新和插入操作的入口类。
  • 它提供同步和异步服务,并且可以自动创建和管理 JDBC 资源(如 Connection、Statement、ResultSet)。
  • QueryRunner 还支持批处理操作,可以一次性执行多个 SQL 语句。
  1. ResultSetHandler:
  • ResultSetHandler 接口负责将 JDBC 的 ResultSet 转换成其他格式的数据。
  • DbUtils 提供了多种 ResultSetHandler 的实现,用于- 将结果集转换为数组、列表、Map、JavaBean 等格式。
  1. RowProcessor:
  • RowProcessor 用于处理行记录,将 ResultSet 的当前行转换为 Java 对象。
  • BasicRowProcessor 是 DbUtils 中的一个默认实现,用于将 SQL 行转换为 Map 或 JavaBean。

逻辑步骤:

  1. 创建 QueryRunner 实例:
  • 可以通过传递 DataSource 或 Connection 来创建 QueryRunner 对象。
  1. 编写 SQL 语句:
  • 准备要执行的 SQL 查询或更新语句。
  1. 选择 ResultSetHandler:
  • 根据需要处理的数据格式选择合适的 ResultSetHandler 实现。
  1. 执行查询或更新:
  • 使用 QueryRunner 的 query 或 update 方法执行 SQL 语句,并传入 ResultSetHandler。
  1. 处理结果:
  • ResultSetHandler 将 ResultSet 转换为相应的数据格式,并返回。
  1. 资源关闭:
  • DbUtils 提供了方法来安全关闭 JDBC 资源,避免资源泄漏。

源代码分析:

以 QueryRunner 和 BeanHandler 为例,分析其源码:

QueryRunner queryRunner = new QueryRunner();
BeanHandler<Emp> handler = new BeanHandler<>(Emp.class);
Emp emp = queryRunner.query("SELECT * FROM emp WHERE id = ?", handler, id);
  1. 创建 QueryRunner 对象:实例化 QueryRunner,准备执行数据库操作。

  2. 创建 BeanHandler 对象:BeanHandler 是 ResultSetHandler 的一个实现,用于将 ResultSet 的每一行转换为一个 JavaBean 对象。

  3. 执行查询:QueryRunner 的 query 方法接受 SQL 语句、ResultSetHandler 和参数,执行查询并返回结果。

QueryRunner 是 Apache DbUtils 中的一个核心类,它封装了 JDBC 的大部分操作,使得执行 SQL 语句更加方便和安全。以下是 QueryRunner 类的详细介绍和源码实现逻辑的分析:

QueryRunner 类介绍:

QueryRunner 类提供了执行各种 SQL 语句的方法,包括:

  • update:用于执行更新操作(如 INSERT、UPDATE、DELETE)。
  • query:用于执行查询操作并返回单个结果。
  • execute:用于执行 DDL 语句或存储过程调用。

它还支持批处理操作,可以一次性执行多个 SQL 语句。

源码实现逻辑:

QueryRunner 的实现涉及到几个关键的步骤:

  1. 获取 JDBC 连接:QueryRunner 的方法通常接收一个 Connection 对象作为参数。在执行 SQL 之前,你需要从数据源或连接池中获取一个 Connection。

  2. 准备 SQL 语句:QueryRunner 使用 PreparedStatement 来准备 SQL 语句。这有助于防止 SQL 注入攻击。

  3. 填充参数:如果 SQL 语句包含占位符(如 ?),QueryRunner 会根据提供的参数数组填充这些占位符。

  4. 执行 SQL:根据执行的 SQL 类型(更新或查询),QueryRunner 会调用适当的方法来执行 SQL。

  5. 处理结果:对于查询操作,QueryRunner 使用 ResultSetHandler 来处理 ResultSet 并将其转换为期望的结果类型。

  6. 资源管理:QueryRunner 提供了方法来确保所有 JDBC 资源(如 PreparedStatement 和 ResultSet)在使用后都被正确关闭,即使在发生异常的情况下也是如此。

源码分析:

以下是 QueryRunner 中 query 方法的一个简化示例,展示了其基本的实现逻辑:

public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException {Connection conn = null;PreparedStatement pstmt = null;ResultSet rs = null;try {conn = getConnection(); // 获取 JDBC 连接pstmt = conn.prepareStatement(sql);this.fillStatement(pstmt, params); // 填充参数rs = pstmt.executeQuery(); // 执行查询return rsh.handle(rs); // 使用 ResultSetHandler 处理结果集} finally {// 关闭资源,即使在发生异常的情况下JdbcUtils.close(rs);JdbcUtils.close(pstmt);JdbcUtils.close(conn);}
}

在这个简化的示例中,query 方法接收 SQL 语句、一个 ResultSetHandler 实例和一些参数。它使用 PreparedStatement 来执行 SQL 语句,并使用提供的 ResultSetHandler 来处理查询结果。

详细解释:

  • getConnection():这是一个从数据源或连接池中获取 Connection 的方法。在实际的 QueryRunner 实现中,这可以是传递给 QueryRunner 构造函数的 DataSource 或在方法中直接传递的 Connection。

  • fillStatement(pstmt, params):这是一个辅助方法,用于将参数绑定到 PreparedStatement 的占位符上。

  • rsh.handle(rs):这是 ResultSetHandler 接口的核心方法,它定义了如何处理 ResultSet。不同的 ResultSetHandler 实现会将 ResultSet 转换为不同的类型,如 JavaBean、Map、List 等。

  • finally 块:确保所有 JDBC 资源在使用后都被正确关闭。这是通过 JdbcUtils.close() 方法实现的,它是一个安全关闭资源的工具方法,可以处理 null 值和潜在的 SQLException。

QueryRunner 的设计哲学是简化 JDBC 编程,同时提供足够的灵活性来处理各种数据库操作。通过封装 JDBC 的复杂性,QueryRunner 使得开发者可以更专注于业务逻辑而不是底层的数据库操作细节。

应用操作

以下是一些 DbUtils 组件的应用案例,展示了如何使用 DbUtils 执行常见的数据库操作:

  1. 基本的数据库查询

使用 QueryRunner 和 BeanHandler 来执行查询并将结果映射到 JavaBean 对象。

QueryRunner queryRunner = new QueryRunner();
BeanHandler<User> handler = new BeanHandler<>(User.class);
User user = queryRunner.query(conn, "SELECT * FROM users WHERE id = ?", handler, 1);
  1. 查询并返回多条记录

使用 BeanListHandler 来处理多条记录,并将结果集映射为 JavaBean 对象的列表。

List<User> users = queryRunner.query(conn, "SELECT * FROM users", new BeanListHandler<>(User.class));
  1. 执行更新操作

使用 QueryRunner 的 update 方法来执行 INSERT、UPDATE 或 DELETE 语句。

int rowsInserted = queryRunner.update(conn, "INSERT INTO users(name, email) VALUES(?, ?)", "John Doe", "john@example.com");
  1. 批量更新

QueryRunner 支持批处理,可以一次性执行多个 SQL 更新操作。

Object[][] batchArgs = {{"John", "john@example.com"},{"Jane", "jane@example.com"}
};
queryRunner.batch(conn, "INSERT INTO users(name, email) VALUES(?, ?)", batchArgs);
  1. 处理聚集函数

使用 ScalarHandler 来处理返回单行单列的查询,如计数或总和。

Long count = queryRunner.query(conn, "SELECT COUNT(*) FROM users", new ScalarHandler<Long>(Long.class));
  1. 使用连接池

DbUtils 可以与连接池(如 DBCP 或 HikariCP)一起使用,以提高性能。

DataSource dataSource = ...; // 初始化数据源
QueryRunner queryRunner = new QueryRunner(dataSource);
// 使用 queryRunner 执行操作,不需要手动关闭连接
  1. 事务处理

DbUtils 提供了一些基本的事务管理方法,但通常与 Spring 或其他框架的事务管理集成更常见。

Connection conn = ...; // 获取数据库连接
try {conn.setAutoCommit(false); // 开始事务// 执行一系列数据库操作conn.commit(); // 提交事务
} catch (SQLException e) {conn.rollback(); // 回滚事务throw e;
} finally {conn.setAutoCommit(true); // 确保设置自动提交DbUtils.closeQuietly(conn); // 关闭连接
}
  1. 自定义 ResultSetHandler

如果预定义的 ResultSetHandler 实现不符合需求,可以自定义实现。

public class CustomHandler implements ResultSetHandler<List<MyBean>> {public List<MyBean> handle(ResultSet rs) throws SQLException {List<MyBean> list = new ArrayList<>();while (rs.next()) {// 根据需要从 ResultSet 中提取数据并创建 MyBean 对象MyBean bean = new MyBean();// ...list.add(bean);}return list;}
}

然后使用自定义的 ResultSetHandler:

List<MyBean> beans = queryRunner.query(conn, "SELECT * FROM my_table", new CustomHandler());

这些案例展示了 DbUtils 在实际应用中的灵活性和强大功能。通过这些组件,DbUtils 使得 JDBC 编程变得更加简洁和易于管理。

最后

DbUtils 的设计思想是简化 JDBC 编程,通过封装 JDBC 操作,减少样板代码,提高开发效率。它通过 QueryRunner、ResultSetHandler 和 RowProcessor 的协同工作,实现了对 JDBC 资源的精细化管理,同时避免了资源泄漏的风险。DbUtils 的使用不涉及复杂的配置和ORM映射,适合需要快速、轻量级数据库操作的场景。

这篇关于apache DbUtils 组件核心原理与应用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/948568

相关文章

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

zoj3820(树的直径的应用)

题意:在一颗树上找两个点,使得所有点到选择与其更近的一个点的距离的最大值最小。 思路:如果是选择一个点的话,那么点就是直径的中点。现在考虑两个点的情况,先求树的直径,再把直径最中间的边去掉,再求剩下的两个子树中直径的中点。 代码如下: #include <stdio.h>#include <string.h>#include <algorithm>#include <map>#

hdu4407(容斥原理)

题意:给一串数字1,2,......n,两个操作:1、修改第k个数字,2、查询区间[l,r]中与n互质的数之和。 解题思路:咱一看,像线段树,但是如果用线段树做,那么每个区间一定要记录所有的素因子,这样会超内存。然后我就做不来了。后来看了题解,原来是用容斥原理来做的。还记得这道题目吗?求区间[1,r]中与p互质的数的个数,如果不会的话就先去做那题吧。现在这题是求区间[l,r]中与n互质的数的和