MySQL---数据库从入门走向大神系列(十五)-Apache的DBUtils框架使用

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MySQL---数据库从入门走向大神系列(十五)-Apache的DBUtils框架使用

DBUtils简介:


commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。因此dbutils成为很多不喜欢hibernate的公司的首选(嗯~商业竞争…..)。

————————————————

版权声明:本文为CSDN博主「谙忆」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qq_26525215/article/details/52212571

commons-dbutilsAPI介绍:


org.apache.commons.dbutils.QueryRunner
org.apache.commons.dbutils.ResultSetHandler
  工具类
org.apache.commons.dbutils.DbUtils

QueryRunner类讲解


该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。

QueryRunner类提供了两个构造方法:

1、默认的构造方法

2、需要一个 javax.sql.DataSource 来作参数的构造方法。

QueryRunner类的主要方法

public Object query(Connection conn, String sql, Object[] params, ResultSetHandler rsh) throws SQLException:

执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理 PreparedStatement 和 ResultSet 的创建和关闭。


public Object query(String sql, Object[] params, ResultSetHandler rsh) throws SQLException:  

几乎与第一种方法一样;唯一的不同在于它不将数据库连接提供给方法,并且它是从提供给构造方法的数据源(DataSource) 或使用的setDataSource 方法中重新获得 Connection。


 public Object query(Connection conn, String sql, ResultSetHandler rsh) throws SQLException : 执行一个不需要置换参数的查询操作。

 

 public int update(Connection conn, String sql, Object[] params) throws SQLException

 用来执行一个更新(插入、更新或删除)操作。

 

 public int update(Connection conn, String sql) throws SQLException:

 用来执行一个不需要置换参数的更新操作。


JAR包准备:


commons-dbutils-1.6.jar(基本包):

http://commons.apache.org/proper/commons-dbutils/download_dbutils.cgi


commons-dbutils-ext.jar(扩展包):

https://github.com/chenhaoxiang/Java/tree/master/Database-support-package


代码演示:

首先准备数据库:

create database hncu character set utf8;
use hncu;
create table person(
    id varchar(30) primary key,
    name varchar(30),
    address varchar(30),
    age int
);
insert into  person(id,name,address,age) values('P001','张三','湖南长沙',20);
insert into  person(id,name,address,age) values('P002','李四','中国北京',25);
insert into  person(id,name,address,age) values('P003','李白','武汉',56);
insert into  person(id,name,address,age) values('P004','张三丰','武当三',78);
insert into  person(id,name,address,age) values('P005','Tom','美国纽约',34);
insert into  person(id,name,address,age) values('P006','Jack','美国旧金山',28);


Connection池是用的c3p0Pool类的:

http://blog.csdn.net/qq_26525215/article/details/52212260

不使用dbUtils工具的数据库查询代码实现

@Test//原来不使用dbUtils工具的数据库查询代码实现
    public void jdbcQuery() throws SQLException{
        List<Person> persons = new ArrayList<Person>();
        Connection con = C3p0Pool.getConnection();
        String sql = "select * from person";
        Statement st = con.createStatement();
        ResultSet rs = st.executeQuery(sql);
        while(rs.next()){
            Person p = new Person();
            p.setId(rs.getString("id"));
            p.setName(rs.getString("name"));
            p.setAddr(rs.getString("address"));
            p.setAge(Integer.parseInt(rs.getString("age")));
            persons.add(p);
        }
        for(Person p:persons){
            System.out.println(p);
        }
    }

结果:

image.png

使用dbUtils工具的数据库查询代码实现

BeanListHandler返回类型为List<>

@Test
    public void dbUtilsQuery() throws SQLException{
        QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
        String sql = "select * from person";
        List<Person> persons = run.query(sql,new BeanListHandler<Person>(Person.class));
        for(Person p:persons){
            System.out.println(p);
        }
    }
数据库的字段名为:address、
public String addr;
    //这里的名字如果和数据库的字段名不同。会出现读取值为null的情况
    //如果要解决,把get和set函数的set/get***写成和数据的字段名一样就可以了。setAddress()/getAddress()
    //或者在查询的时候取别名如:select id,name,address as addr ,age  from person
    //但是最好还是和数据库的字段名一样比较好


MapListHandler返回类型为List<Map<String,Object>>

而且注意,这个与前面的依赖person类的不同,这个不依赖person类,

也就是person的成员变量名可以和数据库的字段名取不同。

    @Test
    public void dbUtilsQuery2() throws SQLException{
        QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
        String sql = "select * from person ";
        List<Map<String, Object>> persons = run.query(sql,new MapListHandler());
        for(Map<String, Object> p:persons){
            System.out.println(p);
        }
    }

DbUtils工具的使用演示: 增删改–用update()

只演示 增,删和改类似:

@Test
    public void save() throws SQLException{
        QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
        //statement方式
        //run.update("insert into person(id,name,address,age) values('P007','Rose','湖南长沙',22) ");
        //prepareStatement方式
        run.update("insert into person(id,name,address,age) values(?,?,?,?)", "P008","Marry","中国西安",34);
    }


如果使用prepareStatement方式,注意参数个数或类型 与 “?”号必须匹配,否则会出异常 。

为 增添加事务处理:

@Test
    public void saveTx() throws SQLException{
        QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
        Connection con = C3p0Pool.getConnection();
        try {
            con.setAutoCommit(false);
            run.update(con, "insert into person(id,name,address,age) values(?,?,?,?)","P011","Tom","浙江杭州",24);
            run.update(con, "insert into person(id,name,address,age) values(?,?,?,?)","P012","Gimo","江苏苏州",45);
            con.commit();
        } catch (Exception e) {
            if(con!=null){
                con.rollback();
                System.out.println("事务回滚了...");
            }
        }finally{
            if(con!=null){
                con.setAutoCommit(true);
                con.close();
            }
        }
    }

注意,实现事务功能时,要传入con对象,且多条语句共处一个事务时,要传入同一个con对象。但如果不实现事务功能,可以不传入con对象。

查询的结果集封装

封装成BeanList

@Test
    public void query2() throws SQLException{
        QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
        //封装成BeanList: 如果值对象中的属性名和表中的字段名不一致,那么该属性的值返回的是null
        //解决方法是采用别名,或者修改set**/get**名
        List<Person> persons = run.query("select id,name,address addr,age from person ",new BeanListHandler<Person>(Person.class) );//用属性名 当 字段别名
        for(Person p:persons){
            System.out.println(p);
        }
    }


封装成MapList

@Test
    public void query3() throws SQLException{
        QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
        String sql = "select * from person";
        List<Map<String, Object>> persons = run.query(sql, new MapListHandler());
        for(Map<String, Object> p:persons){
            System.out.println(p);
        }
    }


封装成BeanList—查询带参数

@Test
    public void query4() throws SQLException{
        QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
        String sql = "select id,name,address,age from person where name like ? and age > ?";
        List<Person> persons = run.query(sql, new BeanListHandler<Person>(Person.class),"%o%",34);
        for(Person p:persons){
            System.out.println(p);
        }
    }


演示批处理功能

@Test
    public void batch() throws SQLException{
        QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
        for(int i=1;i<=100;i++){
            String sql = "insert into person values(?,?,?,?)";
            String str = "000"+i;
            str=str.substring(str.length()-3, str.length());
            String id1="A"+str;
            String id2="B"+str;
            String params[][]={{id1,"Alice"+i,"中国",i+""},{id2,"Bob"+i,"湖南",i+""}};
            run.batch(sql, params);
        }
    }


演示扩展包commons-dbutilss-ext.jar的功能

封装成BeanList—直接通过JavaBean的字节码查询所有

注意,下面的用法要生效,必须给值对象添加注解@Table(value = “person”)

@Test 
    public void query5(){
        ExtQueryRunner run = new ExtQueryRunner(C3p0Pool.getDataSource());
        List<Person> persons = run.query(Person.class);//不用sql语句,,直接查询Bean-List
        for(Person p:persons){
            System.out.println(p);
        }
    }


封装成JavaBean—直接通过JavaBean对象存储进数据库

    @Test
    public void save3(){
        ExtQueryRunner run = new ExtQueryRunner(C3p0Pool.getDataSource());
        Person p = new Person();
        p.setId("A000");
        p.setName("梨子");
        p.setAddress("中国");
        p.setAge(20);
        run.save(p);//不用sql语句,直接存对象
        System.out.println(p);
    }

注意:使用此功能时,需要在JavaBean对象中的每个成员变量上都加上@Column注解!!!


还有注意这里的JavaBean中的addr与数据库的字段名address是不同的,所以需要在JavaBean对象的addr属性上加上一句注解:

@Column(value=”address”)

Person.java

package cn.hncu.dbutils;
import org.apache.commons.dbutils.ext.Column;
import org.apache.commons.dbutils.ext.Table;
/**
 * @author 陈浩翔
 *
 * 2016-8-15
 */
@Table(value = "person")
public class Person {
    @Column
    private String id;
    @Column
    private String name;
    @Column(value="address")
    public String addr;
    //这里的名字如果和数据库的字段名不同。会出现读取值为null的情况
    //如果要解决,把get和set函数的set/get***写成和数据的字段名一样就可以了。
    //或者在查询的时候取别名如:select id,name,address as addr ,age  from person
    //但是最好还是和数据库的字段名一样比较好
    @Column
    private Integer age;
    public Person() {
        super();
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAddress() {
        return addr;
    }
    public void setAddress(String addr) {
        this.addr = addr;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        return true;
    }
    @Override
    public String toString() {
        return "[id=" + id + ", name=" + name + ", addr=" + addr
                + ", age=" + age + "]";
    }
}

转载请附上原文博客链接:

http://blog.csdn.net/qq_26525215

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
26天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
55 3
|
26天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
62 3
|
26天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE &#39;log_%&#39;;`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
82 2
|
1月前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
260 15
|
1月前
|
SQL 关系型数据库 MySQL
数据库数据恢复—Mysql数据库表记录丢失的数据恢复方案
Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、Mysql数据库表中无任何数据或只有部分数据。 2、客户端无法查询到完整的信息。
|
1月前
|
关系型数据库 MySQL 数据库
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。
|
1月前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
1月前
|
存储 人工智能 大数据
The Past, Present and Future of Apache Flink
本文整理自阿里云开源大数据负责人王峰(莫问)在 Flink Forward Asia 2024 上海站主论坛开场的分享,今年正值 Flink 开源项目诞生的第 10 周年,借此时机,王峰回顾了 Flink 在过去 10 年的发展历程以及 Flink社区当前最新的技术成果,最后展望下一个十年 Flink 路向何方。
334 33
The Past, Present and Future of Apache Flink
|
3月前
|
SQL Java API
Apache Flink 2.0-preview released
Apache Flink 社区正积极筹备 Flink 2.0 的发布,这是自 Flink 1.0 发布以来的首个重大更新。Flink 2.0 将引入多项激动人心的功能和改进,包括存算分离状态管理、物化表、批作业自适应执行等,同时也包含了一些不兼容的变更。目前提供的预览版旨在让用户提前尝试新功能并收集反馈,但不建议在生产环境中使用。
933 13
Apache Flink 2.0-preview released
|
3月前
|
存储 缓存 算法
分布式锁服务深度解析:以Apache Flink的Checkpointing机制为例
【10月更文挑战第7天】在分布式系统中,多个进程或节点可能需要同时访问和操作共享资源。为了确保数据的一致性和系统的稳定性,我们需要一种机制来协调这些进程或节点的访问,避免并发冲突和竞态条件。分布式锁服务正是为此而生的一种解决方案。它通过在网络环境中实现锁机制,确保同一时间只有一个进程或节点能够访问和操作共享资源。
136 3

推荐镜像

更多