Java连接数据库 #04# Apache Commons DbUtils

索引

    1. 通过一个简单的调用看整体结构
    2. Examples
    3. 修改JAVA连接数据库 #03# HikariCP中的代码

DbUtils并非是什么ORM框架,只是对原始的JDBC进行了一些封装,以便我们少写一些重复代码。就“用”而言,仅仅需要学习QueryRunner类和ResultSetHandler接口就可以了。它的显著特点就是超级轻量级,总代码量目测似乎还不到一万行。

通过一个简单的调用看整体结构

public class TestDbUtils {
    private static final QueryRunner RUNNER = new QueryRunner(HikariCPUtils.getDs());
    public static void main(String[] args) {
        ResultSetHandler<SimpleUser> handler = new BeanHandler<>(SimpleUser.class);
        SimpleUser user = null;
        try {
            user = RUNNER.query("SELECT * FROM simple_user WHERE username=?", handler, "admin123");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        System.out.println(user);
    }
}

TestDbUtils.java

    /**
     * Calls query after checking the parameters to ensure nothing is null.
     * @param conn The connection to use for the query call.
     * @param closeConn True if the connection should be closed, false otherwise.
     * @param sql The SQL statement to execute.
     * @param params An array of query replacement parameters.  Each row in
     * this array is one set of batch replacement values.
     * @return The results of the query.
     * @throws SQLException If there are database or parameter errors.
     */
    private <T> T query(Connection conn, boolean closeConn, String sql, ResultSetHandler<T> rsh, Object... params)
            throws SQLException {
        if (conn == null) {
            throw new SQLException("Null connection");
        }

        if (sql == null) {
            if (closeConn) {
                close(conn);
            }
            throw new SQLException("Null SQL statement");
        }

        if (rsh == null) {
            if (closeConn) {
                close(conn);
            }
            throw new SQLException("Null ResultSetHandler");
        }

        PreparedStatement stmt = null;
        ResultSet rs = null;
        T result = null;

        try {
            stmt = this.prepareStatement(conn, sql);
            this.fillStatement(stmt, params);
            rs = this.wrap(stmt.executeQuery());
            result = rsh.handle(rs);

        } catch (SQLException e) {
            this.rethrow(e, sql, params);

        } finally {
            try {
                close(rs);
            } finally {
                close(stmt);
                if (closeConn) {
                    close(conn);
                }
            }
        }

        return result;
    }

private T query(Connection conn, boolean closeConn, String sql, ResultSetHandler rsh, Object... params) throws SQLException

AbstractQueryRunner、RowProcessor、ResultSetHandler<T>是Apache Commons DbUtils里的三大主角,通过继承上述抽象类/实现上述接口可以很方便地对API功能进行定制化。另外,想用好DbUtils的话,感觉QueryRunner类和DbUtils类的源码应该是需要经常参照的,通过这两个类可以完成大部分事情,并且灵活度很高。

详细类图参考:http://ju.outofmemory.cn/entry/143920

Examples

官方Examples:http://commons.apache.org/proper/commons-dbutils/examples.html

同步请求的代码在上面已经给出。异步请求的草稿代码如下:

public class DbUtilsSampleDAO {

    private AsyncQueryRunner runner = new AsyncQueryRunner(Executors.newCachedThreadPool());

    public Future<Integer> saveProfile(Profile profile) {
        Future<Integer> future;
        Connection conn = null;
        try {
            conn = ConnectionFactory.getConnection();
            future = runner.update(conn,
                    "INSERT ignore INTO `profiles`.`profile` (`username`, `password`, `nickname`) " +
                            "VALUES (?, ?, ?)", profile.getUsername(), profile.getPassword(), profile.getNickname());
        } catch (SQLException e) {
            throw new DaoException(e);
        } finally {
            try {
                DbUtils.close(conn);
            } catch (SQLException e) {
                throw new DaoException(e);
            }
        }
        return future;
    }

    public static void main(String[] args) {
        DbUtilsSampleDAO dao = new DbUtilsSampleDAO();
        Profile profile = new Profile("myusername", "mypassword", "thisnickname");
        Future<Integer> future = dao.saveProfile(profile);
        try {
            System.out.println(future.get() == 1 ? "更新成功" : "更新失败");
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

修改JAVA连接数据库 #03# HikariCP中的代码

同步更新在GitHub:https://github.com/xkfx/web-test-01

主要的几个类如下:

① QueryRunnerProxy.java

package org.sample.webapp.db.queryrunner;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.sample.webapp.db.connmanager.ConnectionFactory;
import org.sample.webapp.exception.DaoException;

import java.sql.SQLException;

/**
 * 封装DAO层通用代码,不会关闭connection!!!
 */
public class QueryRunnerProxy {

    private QueryRunnerProxy() {
        // Exists to defeat instantiation
    }

    private static QueryRunner runner = new QueryRunner();

    public static int update(String sql, Object... param) {
        int updates = 0;
        try {
            updates = runner.update(ConnectionFactory.getConnection(), sql, param);
        } catch (SQLException e) {
            throw new DaoException(e);
        }
        return updates;
    }

    public static <T> T query(String sql, ResultSetHandler<T> rsh, Object... params) {
        T result = null;
        try {
            result = runner.query(ConnectionFactory.getConnection(), sql, rsh, params);
        } catch (SQLException e) {
            throw new DaoException(e);
        }
        return result;
    }
}

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

② RsHandlers.java

package org.sample.webapp.db.queryrunner;

import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.sample.webapp.entity.Profile;

/**
 * 业务相关,保存各式各样的ResultSetHandler常量
 */
public interface RsHandlers {

    BeanListHandler<Profile> PROFILE_LIST = new BeanListHandler<>(Profile.class);

    BeanHandler<Profile> PROFILE = new BeanHandler<>(Profile.class);
}

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

③ ProfileDAOImpl.java 顺便改为enum了,仅是因为感觉这样写表示单例更清晰。

package org.sample.webapp.dao.impl;

import org.sample.webapp.dao.ProfileDAO;
import org.sample.webapp.db.queryrunner.QueryRunnerProxy;
import org.sample.webapp.db.queryrunner.RsHandlers;
import org.sample.webapp.entity.Profile;

import java.util.List;

/**
 * 该类方法统一抛出DaoException
 */
public enum ProfileDAOImpl implements ProfileDAO {

    INSTANCE;

    @Override
    public int saveProfile(Profile profile) {
        final String sql = "INSERT ignore INTO profile (username, password, nickname) " +
                "VALUES (?, ?, ?)"; // 添加ignore出现重复不会抛出异常而是返回0
        return QueryRunnerProxy.update(sql, profile.getUsername(), profile.getPassword(), profile.getNickname());
    }

    @Override
    public List<Profile> listByNickname(String nickname) {
        final String sql = "SELECT  profile_id AS id,  username,  password,  nickname, last_online AS lastOnline, gender, birthday, location, joined " +
                "FROM profile " +
                "WHERE nickname=?";
        return QueryRunnerProxy.query(sql, RsHandlers.PROFILE_LIST, nickname);
    }

    @Override
    public Profile getByUsername(String username) {
        final String sql = "SELECT  profile_id AS id,  username,  password,  nickname, last_online AS lastOnline, gender, birthday, location, joined " +
                "FROM profile " +
                "WHERE username=?"; // TODO 该字符串会反复创建吗?
        return QueryRunnerProxy.query(sql, RsHandlers.PROFILE, username);
    }

    @Override
    public int updateById(Profile profile) {
        final String sql = "UPDATE profile " +
                "SET nickname=?, gender=?, birthday=?, location=? " +
                "WHERE profile_id=?";
        return QueryRunnerProxy.update(sql, profile.getNickname(), profile.getGender() != null ? String.valueOf(profile.getGender()) : null,
                profile.getBirthday(), profile.getLocation(), profile.getId());
    }

    @Override
    public int updatePassword(String username, String password) {
        final String sql = "UPDATE profile " +
                "SET password=? " +
                "WHERE username=?";
        return QueryRunnerProxy.update(sql, password, username);
    }

    @Override
    public int updateLastOnline(String username) {
        final String sql = "UPDATE profile " +
                "SET last_online=CURRENT_TIMESTAMP " +
                "WHERE username=?";
        return QueryRunnerProxy.update(sql, username);
    }
}

原文地址:https://www.cnblogs.com/xkxf/p/10128082.html

时间: 2024-10-12 08:46:25

Java连接数据库 #04# Apache Commons DbUtils的相关文章

java.lang.ClassNotFoundException: org.apache.commons.dbutils.QueryRunner

七月 28, 2017 11:06:33 下午 org.apache.catalina.core.StandardWrapperValve invoke严重: Servlet.service() for servlet [com.itheima.transfer.web.TransferServlet] in context with path [/WEB19] threw exception [Servlet execution threw an exception] with root ca

Apache Commons DbUtils

1       概述 Commons DBUtils类库是小型的设计于易于使用JDBC的类集合.JDBC资源清理是平凡的,容易出错,以至于这些类从你的代码中抽象出清理代码,剩下你最初真正想要使用JDBC做的代码:查询和更新数据. 使用DBUtils的一些优势: 没有资源泄露的可能性.正确的JDBC编码并不难,但它耗时且乏味.这常常会导致连接泄漏可能很难追踪. 清晰的持久化代码.需要持久化数据到数据库中的代码大幅减少.剩下的代码清晰的表达你的意图没有凌乱的资源清理. 从ResultSet自动填充J

高性能jdbc封装工具 Apache Commons DbUtils 1.6

转载自原文地址:http://gao-xianglong.iteye.com/blog/2166444 前言 关于Apache的DbUtils中间件或许了解的人并不多,大部分开发人员在生成环境中更多的是依靠Hibernate.Ibatis.Spring JDBC.JPA等大厂提供的持久层技术解决方案,或者是企业内部自己研发的持久层技术.但无论如何,使用这些技术的初衷和本质都是为了能够减少企业开发成本,提高生产效率,降低耦合. 放眼企业级项目,Hibernate等ORM产品是首选,而互联网领域,大

高性能jdbc封装工具 Apache Commons DbUtils 1.6(转载)

转载自原文地址:http://gao-xianglong.iteye.com/blog/2166444 前言 关于Apache的DbUtils中间件或许了解的人并不多,大部分开发人员在生成环境中更多的是依靠Hibernate.Ibatis.Spring JDBC.JPA等大厂提供的持久层技术解决方案,或者是企业内部自己研发的持久层技术.但无论如何,使用这些技术的初衷和本质都是为了能够减少企业开发成本,提高生产效率,降低耦合. 放眼企业级项目,Hibernate等ORM产品是首选,而互联网领域,大

Apache Commons DbUtils使用手册

Apache Commons DbUtils使用手册 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs 一.介绍 DBUtils是个小巧的JDBC轻量级封装的工具包,其最核心的特性是在JDBC的基础上做了一层封装,主要是对结果集的封装,可以直接将查询出来的结果集封装成JavaBean,旨在简化JDBC代码混乱与重复.JDBC代码开发,存在很多难点:1)操作过程复杂,代码操作一个模式,大量的重复.2)结果集难以处理.3)到处都强制检查SQLExcepti

java开发_org.apache.commons.lang.StringUtils工具类源码

package org.apache.commons.lang; 18 19 import java.util.ArrayList; 20 import java.util.Collection; 21 import java.util.Iterator; 22 import java.util.List; 23 import java.util.Locale; 24 25 import org.apache.commons.lang.text.StrBuilder; 26 27 /** 28

Java工具类 Apache Commons:commons-lang

Commons Lang The standard Java libraries fail to provide enough methods for manipulation of its core classes. Apache Commons Lang provides these extra methods. Lang provides a host of helper utilities for the java.lang API, notably String manipulatio

Java执行外部程序(Apache Commons Exec)

之前使用Runtime.getRuntime().exec调用外部程序,在Tomcat下会有当前线程一直等待的现象.当时为了解决这个问题,使用新建线程接收外部程序的输出信息,详情请看博客http://blog.csdn.net/accountwcx/article/details/46785437. 后来在网上找到开源的Java调用外部程序类库Apache Commons Exce,这个类库提供非阻塞方法调用外部程序. 官方网址 http://commons.apache.org/proper/

Java运行外部程序(Apache Commons Exec)

之前使用Runtime.getRuntime().exec调用外部程序.在Tomcat下会有当前线程一直等待的现象. 当时为了解决问题,使用新建线程接收外部程序的输出信息.详情请看博客http://blog.csdn.net/accountwcx/article/details/46785437. 后来在网上找到开源的Java调用外部程序类库Apache Commons Exce,这个类库提供非堵塞方法调用外部程序. 官方网址 http://commons.apache.org/proper/c