commons-dbutils使用介绍

简介:

commons-dbutils是Apache开源组织提供的用于操作数据库的工具包。今天为大家介绍一下该包的常用方法。
对于数据库的操作无外乎增删改查,而增删改本质上可以归为一类,操作方式相同,只是SQL语法不同而已,所以我将以修改和查询两类来介绍commons-dbutils的用法。

首先我们来创建一个测试类,使用JUnit进行测试。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;


public class DBUtilsTest
{
   private Connection conn = null;

   @Before
   public void initConnection() throws SQLException, ClassNotFoundException
   {
      printCurrentMethodName();
      Class.forName("org.h2.Driver");
      conn = DriverManager.getConnection("jdbc:h2:h2.db", "test", "123");
   }

   @Before
   public void initDatabase() throws SQLException
   {
      printCurrentMethodName();
      QueryRunner runner = new QueryRunner();
      runner.update(
            conn,
            "CREATE TABLE IF NOT EXISTS USER_INFO (userId VARCHAR(20) PRIMARY KEY, userName VARCHAR(50))");
   }

   @After
   public void destory()
   {
      printCurrentMethodName();
      DbUtils.closeQuietly(conn);
   }

   /**
    * 打印当前运行方法名称
    */
   public void printCurrentMethodName()
   {
      System.out.println(Thread.currentThread().getStackTrace()[2]
            .getMethodName());
      System.out.println("==================================================");
   }
}

在这段测试代码中,我们是用h2作为数据库进行测试以及定义了一些连接、数据库的初始化及销毁的方法。
commons-dbutils中操作数据库的常用类为:QueryRunner
QueryRunner的常用方法如下:

返回值 方法名 说明
int[] batch(Connection conn, String sql, Object[][] params) 批量执行INSERT、UPDATE或DELETE
int[] batch(String sql, Object[][] params) 批量执行INSERT、UPDATE或DELETE
T insert(Connection conn, String sql, ResultSetHandler rsh) 执行一个插入查询语句
T insert(Connection conn, String sql, ResultSetHandler rsh, Object… params) 执行一个插入查询语句
T insert(String sql, ResultSetHandler rsh) 执行一个插入查询语句
T insert(String sql, ResultSetHandler rsh, Object… params) 执行一个插入查询语句
T insertBatch(Connection conn, String sql, ResultSetHandler rsh, Object[][] params) 批量执行插入语句
T insertBatch(String sql, ResultSetHandler rsh, Object[][] params) 批量执行插入语句
T query(Connection conn, String sql, ResultSetHandler rsh) 查询
T query(Connection conn, String sql, ResultSetHandler rsh, Object… params) 查询
T query(String sql, ResultSetHandler rsh) 查询
T query(String sql, ResultSetHandler rsh, Object… params) 查询
int update(Connection conn, String sql) 执行INSERT、UPDATE或DELETE
int update(Connection conn, String sql, Object… params) 执行INSERT、UPDATE或DELETE
int update(Connection conn, String sql, Object param) 执行INSERT、UPDATE或DELETE
int update(String sql) 执行INSERT、UPDATE或DELETE
int update(String sql, Object… params) 执行INSERT、UPDATE或DELETE
int update(String sql, Object param) 执行INSERT、UPDATE或DELETE

修改

我们先来看一下如何使用QueryRunner进行修改操作,在我们的测试代码中添加测试方法:

@Test
public void update() throws SQLException
{
   printCurrentMethodName();
   QueryRunner runner = new QueryRunner();
   String suffix = Long.toHexString(System.currentTimeMillis());
   Integer result = runner.update(conn,
         "insert into USER_INFO(userId, userName) values(?, ?)", suffix,
         "name" + suffix);
   System.out.println("受影响记录条数:" + result);
}

修改的操作相比较而言还是很简单的,在这段测试代码中,我们向数据库中添加了一条记录,在QueryRunner中也是支持动态参数的,可以很方便的绑定参数。

查询

ScalarHandler

ScalarHandler会返回一个对象,用于读取结果集中第一行指定列的数据。这里我们以查询表中总记录数为例:

@Test
public void queryByScalarHandler() throws SQLException
{
   printCurrentMethodName();
   QueryRunner runner = new QueryRunner();
   Number number = runner.query(conn, "select count(*) from USER_INFO",
         new ScalarHandler<Number>());
   System.out.println("总记录记录条数:" + number.intValue());
}

不知大家有没有发现,在ScalarHandler的泛型中,我使用的是Number,解释一下:之前我在使用该方法查询记录条数的时候,不同的数据库返回的数据类型可能不同,有的返回是Integer,而有的却是Long,为了代码的通用,所以在这里我使用了Number

ArrayHandler

ArrayHandler会返回一个数组,用于将结果集第一行数据转换为数组。

@Test
public void queryByArrayHandler() throws SQLException
{
   printCurrentMethodName();
   QueryRunner runner = new QueryRunner();
   Object[] results = runner.query(conn, "select * from USER_INFO",
         new ArrayHandler());
   System.out.println(Arrays.asList(results));
}

ArrayListHandler

ArrayListHandler会返回一个集合,集合中的每一项对应结果集指定行中的数据转换后的数组。

@Test
public void queryByArrayListHandler() throws SQLException
{
   printCurrentMethodName();
   QueryRunner runner = new QueryRunner();
   List<Object[]> results = runner.query(conn, "select * from USER_INFO",
         new ArrayListHandler());
   for (Object[] object : results)
   {
      System.out.println(Arrays.asList(object));
   }
}

KeyedHandler

KeyedHandler会返回一个Map,我们可以指定某一列的值作为该Map的键,Map中的值为对应行数据转换的键值对,键为列名。

@Test
public void queryByKeyedHandler() throws SQLException
{
   printCurrentMethodName();
   QueryRunner runner = new QueryRunner();
   Map<String, Map<String, Object>> results = runner.query(conn,
         "select * from USER_INFO", new KeyedHandler<String>());
   System.out.println(results);
}

ColumnListHandler

ColumnListHandler会返回一个集合,集合中的数据为结果集中指定列的数据。

@Test
public void queryByColumnListHandler() throws SQLException
{
   printCurrentMethodName();
   QueryRunner runner = new QueryRunner();
   List<String> results = runner.query(conn, "select * from USER_INFO",
         new ColumnListHandler<String>());
   System.out.println(results);
}

MapHandler

MapHandler会将结果集中第一行数据转换为键值对,键为列名。

@Test
public void queryByMapHandler() throws SQLException
{
   printCurrentMethodName();
   QueryRunner runner = new QueryRunner();
   Map<String, Object> results = runner.query(conn,
         "select * from USER_INFO", new MapHandler());
   System.out.println(results);
}

MapListHandler

MapHandler会将结果集中的数据转换为一个集合,集合中的数据为对应行转换的键值对,键为列名

@Test
public void queryByMapListHandler() throws SQLException
{
   printCurrentMethodName();
   QueryRunner runner = new QueryRunner();
   List<Map<String, Object>> results = runner.query(conn,
         "select * from USER_INFO", new MapListHandler());
   System.out.println(results);
}

BeanHandler

BeanHandler实现了将结果集第一行数据转换为Bean对象,在实际应用中非常方便。

在编写测试代码之前,我们先来编写一个对应的Bean类:

import java.text.MessageFormat;

public class UserInfo
{
   private String userId;
   private String userName;

   public String getUserId()
   {
      return userId;
   }

   public void setUserId(String userId)
   {
      this.userId = userId;
   }

   public String getUserName()
   {
      return userName;
   }

   public void setUserName(String userName)
   {
      this.userName = userName;
   }

   @Override
   public String toString()
   {
      return MessageFormat
            .format("[userId:{0},userName:{1}]", userId, userName);
   }
}

接下来,我们来编写测试代码:

@Test
public void queryByBeanHandler() throws SQLException
{
   printCurrentMethodName();
   QueryRunner runner = new QueryRunner();
   UserInfo results = runner.query(conn, "select * from USER_INFO",
         new BeanHandler<UserInfo>(UserInfo.class));
   System.out.println(results);
}

BeanListHandler

BeanHandler只转换结果集的第一行,而BeanListHandler会将结果集的所有行进行转换,返回一个集合。

@Test
public void queryByBeanListHandler() throws SQLException
{
   printCurrentMethodName();
   QueryRunner runner = new QueryRunner();
   List<UserInfo> results = runner.query(conn, "select * from USER_INFO",
         new BeanListHandler<UserInfo>(UserInfo.class));
   System.out.println(results);
}

BeanMapHandler

BeanMapHandler也会将结果集转换为Bean对象,不过返回的是已指定列的值作为键的键值对。

@Test
public void queryByBeanMapHandler() throws SQLException
{
   printCurrentMethodName();
   QueryRunner runner = new QueryRunner();
   Map<String, UserInfo> results = runner.query(conn,
         "select * from USER_INFO", new BeanMapHandler<String, UserInfo>(
               UserInfo.class));
   System.out.println(results);
}

完整测试代码

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.BeanMapHandler;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.KeyedHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.After;
import org.junit.Before;

public class DBUtilsTest
{
   private Connection conn = null;

   @Before
   public void initConnection() throws SQLException, ClassNotFoundException
   {
      printCurrentMethodName();
      Class.forName("org.h2.Driver");
      conn = DriverManager.getConnection("jdbc:h2:h2.db", "test", "123");
   }

   @Before
   public void initDatabase() throws SQLException
   {
      printCurrentMethodName();
      QueryRunner runner = new QueryRunner();
      runner.update(
            conn,
            "CREATE TABLE IF NOT EXISTS USER_INFO (userId VARCHAR(20) PRIMARY KEY, userName VARCHAR(50))");
   }

   public void update() throws SQLException
   {
      printCurrentMethodName();
      QueryRunner runner = new QueryRunner();
      String suffix = Long.toHexString(System.currentTimeMillis());
      Integer result = runner.update(conn,
            "insert into USER_INFO(userId, userName) values(?, ?)", suffix,
            "name" + suffix);
      System.out.println("受影响记录条数:" + result);
   }

   public void queryByScalarHandler() throws SQLException
   {
      printCurrentMethodName();
      QueryRunner runner = new QueryRunner();
      Number number = runner.query(conn, "select count(*) from USER_INFO",
            new ScalarHandler<Number>());
      System.out.println("总记录记录条数:" + number.intValue());
   }

   public void queryByArrayHandler() throws SQLException
   {
      printCurrentMethodName();
      QueryRunner runner = new QueryRunner();
      Object[] results = runner.query(conn, "select * from USER_INFO",
            new ArrayHandler());
      System.out.println(Arrays.asList(results));
   }

   public void queryByArrayListHandler() throws SQLException
   {
      printCurrentMethodName();
      QueryRunner runner = new QueryRunner();
      List<Object[]> results = runner.query(conn, "select * from USER_INFO",
            new ArrayListHandler());
      for (Object[] object : results)
      {
         System.out.println(Arrays.asList(object));
      }
   }

   public void queryByKeyedHandler() throws SQLException
   {
      printCurrentMethodName();
      QueryRunner runner = new QueryRunner();
      Map<String, Map<String, Object>> results = runner.query(conn,
            "select * from USER_INFO", new KeyedHandler<String>());
      System.out.println(results);
   }

   public void queryByColumnListHandler() throws SQLException
   {
      printCurrentMethodName();
      QueryRunner runner = new QueryRunner();
      List<String> results = runner.query(conn, "select * from USER_INFO",
            new ColumnListHandler<String>());
      System.out.println(results);
   }

   public void queryByMapHandler() throws SQLException
   {
      printCurrentMethodName();
      QueryRunner runner = new QueryRunner();
      Map<String, Object> results = runner.query(conn,
            "select * from USER_INFO", new MapHandler());
      System.out.println(results);
   }

   public void queryByMapListHandler() throws SQLException
   {
      printCurrentMethodName();
      QueryRunner runner = new QueryRunner();
      List<Map<String, Object>> results = runner.query(conn,
            "select * from USER_INFO", new MapListHandler());
      System.out.println(results);
   }

   public void queryByBeanHandler() throws SQLException
   {
      printCurrentMethodName();
      QueryRunner runner = new QueryRunner();
      UserInfo results = runner.query(conn, "select * from USER_INFO",
            new BeanHandler<UserInfo>(UserInfo.class));
      System.out.println(results);
   }

   public void queryByBeanListHandler() throws SQLException
   {
      printCurrentMethodName();
      QueryRunner runner = new QueryRunner();
      List<UserInfo> results = runner.query(conn, "select * from USER_INFO",
            new BeanListHandler<UserInfo>(UserInfo.class));
      System.out.println(results);
   }

   public void queryByBeanMapHandler() throws SQLException
   {
      printCurrentMethodName();
      QueryRunner runner = new QueryRunner();
      Map<String, UserInfo> results = runner.query(conn,
            "select * from USER_INFO", new BeanMapHandler<String, UserInfo>(
                  UserInfo.class));
      System.out.println(results);
   }

   @After
   public void destory()
   {
      printCurrentMethodName();
      DbUtils.closeQuietly(conn);
   }

   /**
    * 打印当前运行方法名称
    */
   public void printCurrentMethodName()
   {
      System.out.println(Thread.currentThread().getStackTrace()[2]
            .getMethodName());
      System.out.println("==================================================");
   }
}
目录
相关文章
|
SQL Ubuntu 关系型数据库
PostgreSQL介绍和PostgreSQL包安装
PostgreSQL 是一个功能强大、可扩展的开源关系型数据库系统,以其可靠性、数据完整性和高性能著称。它支持复杂查询、事务、多版本并发控制及丰富的数据类型,适用于各种应用场景。本文介绍 PostgreSQL 的核心特性,并详细说明在多种 Linux 发行版上的安装与配置方法,帮助用户快速部署和使用该数据库系统。
1152 0
|
8月前
|
机器学习/深度学习 人工智能 自然语言处理
学AI应该关注哪些博主或达人?这10位2025年最值得收藏的创作者请收好
2025年,AI重塑商业与社会,学习AI成必备技能。本文精选10位最具影响力的AI领域创作者,涵盖技术、商业、创业、战略等维度,助你精准找到学习路径,掌握时代先机。
1446 0
|
11月前
|
存储 缓存 资源调度
# Qwen3-8B 与 ChatGPT-4o Mini 的 TTFT 性能对比与底层原理详解
Qwen3-8B 是通义实验室推出的80亿参数模型,支持32K上下文,采用FP8量化和CUDA优化,提升推理效率;ChatGPT-4o Mini 为OpenAI轻量模型,参数约3.8B,支持128K上下文,通过蒸馏技术实现低延迟。两者在TTFT、长文本处理和部署优化上各有优势,适用于不同应用场景。
1716 9
|
人工智能 自然语言处理 开发者
Co-op Translator:微软推出面向开发者的开源多语言翻译工具
微软推出的开源多语言翻译工具Co-op Translator,基于Azure AI服务,能够自动化处理项目文档和图像中的文本翻译,简化技术文档的本地化流程,促进全球开发者协作。
581 25
Co-op Translator:微软推出面向开发者的开源多语言翻译工具
|
人工智能 自然语言处理 搜索推荐
[AI Mem0 Platform] 快速开始,为您的AI应用注入长期记忆和个性化能力!
[AI Mem0 Platform] 快速开始,为您的AI应用注入长期记忆和个性化能力!
1596 0
|
固态存储 C++ 计算机视觉
Windows平台GIMP 2.10下载教程:零基础入门高级图像编辑
GIMP(GNU Image Manipulation Program)是一款开源跨平台图像编辑工具,支持图层管理、高级修图、色彩校正等功能,广泛应用于平面设计和照片修复。其优势包括全功能免费、插件生态丰富(600+扩展插件)、硬件要求低(1GB内存即可流畅运行)。本文详细介绍GIMP的软件定位、安装流程、首次配置及常见问题解答,帮助用户快速上手并充分利用其强大功能。
|
监控 测试技术 数据库
详解Hyper-V虚拟机CPU分配方法
在Hyper-V环境中,合理分配虚拟机的CPU资源至关重要。vCPU是物理CPU的虚拟化表示,管理员可通过指定处理器数量、核心数、设置兼容性和亲和性、启用动态分配等方法优化性能。使用性能监视工具监控并调整CPU资源,避免过度分配,确保虚拟机稳定运行。定期评估和优化资源分配策略,以适应业务变化,保持最佳性能。
|
数据挖掘 开发工具 Android开发
安卓与iOS开发环境的对比分析
在移动应用开发的广阔领域中,安卓和iOS作为两大主导平台,各自拥有独特的开发环境。本文旨在深入探讨安卓的开放性与灵活性、多样化的开发工具以及广泛的设备兼容性,并与iOS的开发环境进行比较。通过引用最新的行业数据,分析开发者社区规模、应用市场的分布情况,并结合具体的开发案例,揭示两种环境在实际应用中的表现差异。文章将详细阐述安卓开发环境的多方面优势,同时客观评估其面临的挑战,为移动应用开发者提供全面而深入的见解。
446 31
|
存储 关系型数据库 MySQL
Mysql行格式DYNAMIC和COMPACT区别
总之,选择哪种行格式取决于具体的应用场景,如数据类型分布、读写比例、存储与性能需求等。在处理大量文本或二进制数据且对存储空间敏感的应用中,DYNAMIC格式可能是更好的选择;而对于混合型数据且对读取性能有一定要求的场景,COMPACT格式可能更合适。在设计数据库时,评估这些因素并进行适当测试,可以帮助确定最适合的行格式。
1141 0
|
Java 应用服务中间件
Springboot启动的时候初始化的线程池默认配置tomcat
Springboot启动的时候初始化的线程池默认配置tomcat
617 1