提到:原生的JDBC开发起来十分不方便,重复代码较多且容易出错,今天要介绍的是Apache开源的JDBC封装工具包,官网上对它的描述是

不再有资源泄漏的可能,原生的JDBC很有可能异常或其他原因导致连接未正常关闭而导致难以追踪的连接泄漏

大大减少数据库操作代码,让Dao层更简洁、清晰

从ResultSet自动填充JavaBean属性。您无需通过调用setter方法手动将列值复制到bean实例中。ResultSet的每一行都可以由一个完全填充的bean实例表示。

总的来说,DButils的特点是小而精,使用它不会有性能上的损失。复杂的框架或多或少会影响性能,但互联网应用更重要的是快速的开发和迭代,这也是框架流行的原因。框架是对底层的封装,让开发者不再担心底层繁琐的处理而专注业务开发,DBUtils则是对JDBC最小化的封装,让JDBC操作变得更加简单,代码更易读。

对于使用DBUtils操作数据库的开发人员而言,只需要关注三个核心的类/接口

DbUtils:连接数据库对象----jdbc辅助方法的集合类,线程安全

作用:控制连接,控制书屋,控制驱动加载额一个类。

QueryRunner:SQL语句的操作对象,可以设置查询结果集的封装策略,线程安全。

ResultSetHandler:封装数据的策略对象------将封装结果集中的数据,转换到另一个对象

说了这么多,show me the code!

基本使用

首先用maven构建项目,pom.xml如下

1<project xmlns=".0"  2xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  3xsi:schemaLocation=".0  4http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5<modelVersion>4.0.0</modelVersion> 6<groupId>com.cetc</groupId> 7<artifactId>dbutils</artifactId> 8<version>0.0.1-SNAPSHOT</version> 9<properties>10    <maven.compiler.target>1.8</maven.compiler.target>11    <maven.compiler.source>1.8</maven.compiler.source>12</properties>13<dependencies>14  <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->15    <dependency>16        <groupId>mysql</groupId>17        <artifactId>mysql-connector-java</artifactId>18        <version>5.1.38</version>19    </dependency>20    <!-- https://mvnrepository.com/artifact/commons-dbutils/commons-dbutils -->21    <dependency>22        <groupId>commons-dbutils</groupId>23        <artifactId>commons-dbutils</artifactId>24        <version>1.7</version>25    </dependency></dependencies>29</project>基本的使用只需要引入 mysql-connector-java和commons-dbutils,百度 包名+mvn即可得到想要的依赖,比如dbutils

新建数据jdbcdb,并执行如下脚本

1CREATE TABLE person(2id int primary key auto_increment,3name varchar(20),4age int(2),5description varchar(100)6); 数据库构建好了,为了让Java程序连接上数据库,用一个properties文件保存数据库的配置信息

同时新建一个工具类,管理数据库连接

1   /** 2 * 数据库操作工具类 3 *  4 * @author lamp 5 *  6 */ 7public class DBUtils { 8 9// 数据库连接地址10public static String URL;11// 用户名12public static String USERNAME;13// 密码14public static String PASSWORD;15// mysql的驱动类16public static String DRIVER;1718private static ResourceBundle rb = ResourceBundle.getBundle("dbutils.db.db-config");1920private DBUtils() {21}2223// 使用静态块加载驱动程序24static {25    URL = rb.getString("jdbc.url");26    USERNAME = rb.getString("jdbc.username");27    PASSWORD = rb.getString("jdbc.password");28    DRIVER = rb.getString("jdbc.driver");29    try {30        Class.forName(DRIVER);31    } catch (ClassNotFoundException e) {32        e.printStackTrace();33    }34}3536// 定义一个获取数据库连接的方法37public static Connection getConnection() {38    Connection conn = null;39    try {40        conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);41    } catch (SQLException e) {42        e.printStackTrace();43        System.out.println("获取连接失败");44    }45    return conn;46}4748// 关闭数据库连接49public static void close(ResultSet rs, Statement stat, Connection conn) {50    DbUtils.closeQuietly(conn, stat, rs);51}5253}主要是获取连接,当然这里还可以用数据库连接池,更好的管理数据库连接。为了利用Java操作数据库还需要建立Dao层和实体层:分别对应数据库的增删改查以及数据库表映射关系

1public class Person {2private int id;3private String name;4private int age;5private String description;6//省略get和set方法7}Dao层

1public interface PersonDao { 2// 添加方法 3public void add(Person p) throws SQLException; 4 5// 更新方法 6public void update(Person p) throws SQLException; 7 8// 删除方法 9public void delete(int id) throws SQLException;1011// 查找方法12public Person findById(int id) throws SQLException;1314// 查找所有15public List<Person> findAll() throws SQLException;1617// 查询有几条记录18public long personCount() throws SQLException;1920}实现

1public class PersonDaoImpl implements PersonDao { 2private QueryRunner runner = null;//查询运行器 3public PersonDaoImpl(){ 4    runner = new QueryRunner(); 5} 6 7//方法:向数据库中添加一条记录 8@Override 9public void add(Person p) throws SQLException {10    String sql = "insert into 11    person(name,age,description)values(?,?,?)";12    runner.update(DBUtils.getConnection(), sql, p.getName(), 13    p.getAge(),p.getDescription());14}1516//方法:根据id向数据库中修改某条记录17@Override18public void update(Person p) throws SQLException {19    String sql = "update person set 20    name=?,age=?,description=? where id=?";21    runner.update(DBUtils.getConnection(), sql, 22    p.getName(),p.getAge(),p.getDescription(),p.getId());23}2425//方法:根据id删除数据库中的某条记录26@Override27public void delete(int id) throws SQLException {28    String sql = "delete from person where id=?";29    runner.update(DBUtils.getConnection(), sql, id);30} //方法:使用BeanHandler查询一个对象    34@Override35public Person findById(int id) throws SQLException {36    String sql = "select name,age,description from person 37    where id=?";38    Person p = runner.query(DBUtils.getConnection(), sql, 39    new BeanHandler<Person>(Person.class),id);40    return p;41}4243//方法:使用BeanListHandler查询所有对象44@Override45public List<Person> findAll() throws SQLException {46    String sql = "select name,age,description from person";47    List<Person> persons = 48     runner.query(DBUtils.getConnection(), sql, new 49     BeanListHandler<Person>(Person.class));50    return persons;51}5253//方法:使用ScalarHandler查询一共有几条记录54@Override55public long personCount()throws SQLException{56    String sql = "select count(id) from person";57    return runner.query(DBUtils.getConnection(),sql, new 58    ScalarHandler<Long>());59}6061}从Dao层的代码来看,只需要写好sql语句并调用QueryRunner 的相关方法就可以实现数据库的增删改查,数据库结果集映射成Bean以及集合的方法则由ResultSetHander的各个子类来完成,大大的简化了操作,业务代码里面也不需要额外的清理工作。

DBUtil是一个小而精的JDBC封装包,让dao层的业务代码更加清晰,缺点是功能有限,没有提供ORM功能,即对象-关系映射功能(java类与数据库表的映射),大量的SQL代码都在业务层,不是特别优雅。但性能与简洁是其最大的优点。