DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。简要来说就是配合数据库连接池简化对数据库的操作代码,数据库连接池简化了连接操作,而DBUtils简化了增删改查操作,底层由DbUtils工具实现,我们只需要关注用法和了解实现逻辑即可。
DBUtils工具
为了更加简单地使用JDBC,Apache组织提供了一个工具类库commons-dbutils,它是操作数据库地一个组件,实现一个对JDBC的简单封装,可以在不影响性能的情况下极大地简化JDBC地编码工作量。
API介绍
commons-dbutils的核心是两个类org.apache.commons.DbUtils、org.apache.commons.dbutils.QueryRunner和一个接口org.apache.commons.dbutils.ResultSetHealer。
DBUtils类
DBUtils类主要为如关闭连接、装载JDBC驱动程序之类的常规工作提供方法,它提供的方法都是静态方法。
1、close()方法
在DBUtils类中,提供了三个重载的close()方法,这些方法都是用来关闭数据连接,并且在关闭连接时,首先会检查参数是否为NULL,如果不是,该方法就会关闭Connection、Statement、ResultSet这三个对象。
2、closeQuietly(Connection conn,Statement stmt,ResultSet rs)方法
该方法用于关闭Connection、Statement和ResultSet对象。与close()方法相比,closeQuietly()方法不仅能Connection、Statement和ResultSet对象为NULL的情况下避免关闭,还能隐藏一些在程序中抛出的SQL异常。
3、commitAndCloseQuietly(Connection conn)方法
commitAndCloseQuietly()方法用来提交连接,然后关闭连接,并且在关闭连接时不抛出异常。
4、loadDriver(java.lang.String driverClassName)方法
loadDriver()方法用于装载并注册JDBC驱动程序,如果成功就返回true。使用该方法时,不需要捕捉ClassNotFoundException异常。
QueryRunner类
QueryRunner类简化了执行SQL语句的代码,它与ResultSetHandler组合在一起就能完成大部分的数据库操作,大大减少编码量。
QueryRunner类提供了两个构造方法,一个是默认的构造方法,一个是需要javax.sql.DataSource作为参数的构造方法。因此在不用为一个方法提供一个数据库连接的情况下,提供给构造器的DataSource就可以用来获得连接。但是,在使用JDBC操作数据库时,需要使用Connection对象对事务进行操作,QueryRunner类提供了不同的方法。
1、query(Connection conn,String sql,ResultSetHandler rsh,Object[] params)方法
该方法用于执行查询操作,其中,参数params表示一个对象数组,该数组中每个元素的值都被用来作为查询语句的置换参数。需要注意的是,该方法会自动处理PreparedStatement和ResultSet的创建和关闭。
值得一提的是,QueryRunner中还有一个方法是query(Connection conn,String sql,Object[] params,ResultSetHandler rsh)该方法与上述方法唯一不同的地方就是参数的位置。但是可变参数必须位于最后一项,所以此方法已过期。
2、query(String sql,ResultSetHandler rsh,Object[] params)方法
该方法用于执行查询操作,与第一个方法相比,它不需要将Connection对象传递给方法,它可以从提供给构造方法的数据源DataSource或使用的setDataSource()方法中获得连接。
3、query(Connection conn,String sql,ResultSetHandler rsh)方法
该方法用于执行一个不需要置换参数的查询结果。
4、update(Connection conn,String sql,Object[] params)方法
该方法用于执行插入、更新或者删除操作,其中,参数params表示SQL语句中的置换参数。
5、update(Connection conn,String sql)方法
该方法用于执行插入、更新或者删除操作,它不需要置换参数。
ResultSetHandler接口
ResultSetHandler接口用于处理ResultSet结果集,它可以将结果集中的数据转为不同的形式。根据结果集中数据类型的不同,ResultSetHandler提供了不同的实现类。
1)AbstractKeyedHandler:该类为抽象类,能够把结果集里面的数据转换为用Map存储。
2)AbstractListHandler:该类为抽象类,能够把结果集里面的数据转化为用List存储。
3)ArrayHandler:把结果集中的第一行数据转成对象数组。
4)ArrayListHandler:把结果集中的每一行数据转成一个对象数组,再将数组存放到List中。
5)BaseResultSetHandler:把结果集转化为其他对象的扩展。
6)BeanHandler:将结果集中的第一行数据存放到一个对应的javaBean实例中。
7)BeanListHandler:把结果集中的每一行数据存放到一个对应的javaBean实例中,再将JavaBean实例存放到List中。
8)BeanMapHandler:把结果集中的每一行数据存放到一个对应的javaBean实例中,再根据指定的key把每个JavaBean再存放到一个Map里。
9)ColumnListHandler:将结果集中的某一列的数据存放到List中
10)KeyedHandler:把结果集中的每一行数据封装到一个Map中,再根据指定的key把每个JavaBean再存放到一个Map里。
11)MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value是对应的值。
12)MapListHandler:把结果集中的每一行数据封装到一个Map中,再存放到List中。
13)ScalarHandler:将结果集中某一条记录的其中一列的数据存储成Object对象。
另外,在ResultSetHandler接口中,提供了一个单独的方法handle(java.sql.ResultSet rs),如果上述实现类没有提供想要的功能,可以通过自定义一个实现ResultSetHandler接口的类,然后通过重写handle()方法,实现结果集的处理。
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.3.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.10</version>
</dependency>
工具
public class Dbutils {
private DruidDataSource dataSource;
@BeforeMethod
public void testBefore() throws IOException, ClassNotFoundException, SQLException {
/*Properties pros=new Properties();
//properties.load(ClassLoader.getSystemClassLoader().getResourceAsStream("/jdbc.properties"));
pros.load(Dbutils.class.getResourceAsStream("/jdbc.properties"));
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
Class.forName(driverClass);
Connection con = DriverManager.getConnection(url,user,password)*/
Properties properties=new Properties();
properties.load(Dbutils.class.getResourceAsStream("/jdbc.properties"));
dataSource = new DruidDataSource();
dataSource.configFromPropety(properties);
}
@Test
public void test() throws SQLException {
DruidPooledConnection dpc = dataSource.getConnection();
PreparedStatement preparedStatement=dpc.prepareStatement("show tables");
ResultSet resultSet=preparedStatement.executeQuery();
while(resultSet.next()) {
System.out.println(resultSet.getString(1));
}
}
}
配置文件
druid.name=myDruid
druid.url=jdbc:mysql://localhost:3306/dc?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
druid.driverClassName=com.mysql.jdbc.Driver
druid.username=root
druid.password=root
DbUtils:连接数据库对象----jdbc辅助方法的集合类,线程安全
QueryRunner 中提供对sql语句操作的API.
ResultSetHandler 接口,用于定义select操作后,怎样封装结果集.
DbUtils 类,它就是一个工具类,定义了关闭资源与事务处理的方法
跳转到目录
提供数据源: 使用传过来的数据源的连接对象
构造方法
QueryRunner(DataSource) : 创建核心类,并提供数据源,内部自己维护Connection
普通方法
1 update(String sql , Object ... params): 执行DML语句 用于执行增删改语句
2 query(String sql , ResultSetHandler , Object ... params) : 执行DQL语句,并将查询结果封装到对象中。用于执行查询语句
不提供数据源: 需要自己提供连接对象
3.batch():用于执行批处理
构造方法
QueryRunner() : 创建核心类,没有提供数据源,在进行具体操作时,需要手动提供Connection
普通方法
update(Connection conn , String sql , Object … params) : 使用提供的Connection,完成
DML语句
query(Connection conn , String sql , ResultSetHandler , Object … params) : 使用提供的Connection,执行DQL语句,并将查询结果封装到对象中。
QueryRunner实现添加、更新、删除操作
跳转到目录
update(String sql, Object… params) : 用来完成表数据的增加、删除、更新操作
queryRunner.update(sql):针对增加、删除、修改
queryRunner.query(sql,rsh):针对查询
@Test
public void insert() throws Exception {
// 获取一个用来执行SQL语句对象
QueryRunner qr = new QueryRunner(dataSource);
String sql = "INSERT INTO stu(name, score) VALUES(?, ?)";
Object[] params = {"百岁山", "50"};
int count = qr.update(sql, params);
System.out.println("执行成功:=" + count);
}
@Test
public static void insert(){
QueryRunner qr = new QueryRunner();
String sql = "insert into student values(112,'张三',19)";
Connection conn = null;
try {
conn = JDBCUtils.getConnection();
int count = qr.update(conn,sql);
System.out.println(count);
DbUtils.closeQuietly(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void update() throws Exception {
QueryRunner qr = new QueryRunner(dataSource);
String sql = "UPDATE stu SET name=?,score=? WHERE id=?";
Object[] params = {"芒果99", "99", 6};
int count = qr.update(sql, params);
System.out.println(count);
}
@Test
public static void update(){
QueryRunner qr = new QueryRunner();
String sql = "update student set sage= sage+10 where sno = 110";
Connection conn = null;
try {
conn = JDBCUtils.getConnection();
int count = qr.update(conn,sql);
System.out.println(count);
DbUtils.closeQuietly(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
、
@Test
public void delete() throws SQLException {
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql = "DELETE from stu WHERE id = ?";
Object[] params = {6};
int r = queryRunner.update(sql, params);
System.out.println(r);
}
@Test
public static void delete(){
QueryRunner qr = new QueryRunner();
String sql = "delete from student where sno = 112";
Connection conn = null;
try {
conn = JDBCUtils.getConnection();
int count = qr.update(conn,sql);
System.out.println(count);
DbUtils.closeQuietly(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
QueryRunner实现查询操作
跳转到目录
query(String sql, ResultSetHandler rsh, Object… params) 用来完成表数据的查询操作
参数:
String sql: sql语句,参数用?替代
ResultSetHandler<T> rsh: 结果集处理器,接口,必然传递实现类对象
Object … params: 可变参数,传递参数列表,数组.
作用: 给sql中?进行赋值.
ResultSetHandler结果集
跳转到目录
BeanHandler:将结果集中第一条记录封装到一个指定的JavaBean中。
BeanListHandler:将结果集中每一条记录封装到指定的JavaBean中,将这些JavaBean在封装到List集合中
ScalarHandler:它是用于单数据。例如select count(*) from表操作。
ColumnListHandler:将结果集中指定的列的值,封装到一个List集合中
JavaBean
跳转到目录
JavaBean就是一个类,在开发中常用于封装数据,。具有如下特性.
需要实现接口:java.io.Serializable ,通常实现接口这步骤省略了,不会影响程序。
提供私有字段:private 类型 字段名;
提供getter/setter方法:
提供无参构造
BeanHandler
跳转到目录
查询数据表结果集处理其中一种方式:
BeanHandler处理方式 将数据表的结果集第一行数据,封装成JavaBean类的对象
构造方法: BeanHandler(Class<T> type) 传递一个Class类型对象,将结果封装到哪个类的对象
@Test
public void testQueryBeanHandler() throws Exception{
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql = "SELECT * FROM stu WHERE id = ?";
Object[] params = {5};
// 查询并封装
Stu pro = queryRunner.query(sql, new BeanHandler<>(Stu.class), params);
System.out.println(pro);
}
BeanListHandler
跳转到目录
查询数据表结果集处理其中一种方式:
BeanListHandler处理方式 将数据表的每一行数据,封装成JavaBean类对象 ,多行数据了,多个JavaBean对象,存储List集合.
@Test
public void testQueryBeanListHandler() throws Exception{
QueryRunner queryRunner = new QueryRunner(DBCPUtil.getDataSource());
String sql = "SELECT * FROM product";
Object[] params = {};
List<Product> pros = queryRunner.query(sql, new BeanListHandler<Product>(Product.class), params);
for (Product pro : pros) {
System.out.println(pro);
}
}
ScalarHander
跳转到目录
作用: 把查询结果的某一列,存储到List集合对象
构造方法:
public ScalarHandler(): 获取查询结果的第一行的第一列
public ScalarHandler(int index): 获取查询结果的第一行的第index列
public ScalarHandler(String ColumnName): 获取查询结果的第一行的ColumnName列
@Test
public void testQueryScalarHandler() throws Exception{
QueryRunner queryRunner = new QueryRunner(DruidUtil.getDataSource());
String sql = "SELECT * FROM product WHERE pid = ?";
Object[] params = {2};
// 表示查询第二行的第二列
Object o = queryRunner.query(sql, new ScalarHandler(2), params);
System.out.println(o);
}
ColumnListHandler
跳转到目录
获取数据库某一列的值, 通常用于汇总; 常用于 聚合函数
作用: 把查询结果的某一列,存储到List集合对象.用于 聚合函数
构造方法:
public ColumnListHandler(): 把第一列的内容存储到List集合中
public ColumnListHandler(int index): 把指定编号列的内容存储到List集合中
public ColumnListHandler(String ColumnName): 把指定列名对应列的内容存储到List集合中
@Test
public void testQueryColumnListHandler() throws Exception{
QueryRunner queryRunner = new QueryRunner(C3P0Util.getDataSource());
String sql = "SELECT * FROM product";
// List<Object> list = queryRunner.query(sql, new ColumnListHandler());// 默认查询第一列
// List<Object> list = queryRunner.query(sql, new ColumnListHandler(2)); // 查询关系表指定的第二列
List<Object> list = queryRunner.query(sql, new ColumnListHandler("pname"));
for (Object o : list) {
System.out.println(o);
}
}
2.ResultSetHandler接口
1.ArrayHandler:将查询结果的第一行数据,保存到Object数组中
public static void arrayHandler(){
QueryRunner qr = new QueryRunner();
String sql = "select * from student";
try {
Connection conn = JDBCUtils.getConnection();
Object[] query = qr.query(conn, sql, new ArrayHandler());
for(Object obj : query)
System.out.print(obj);
DbUtils.closeQuietly(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
2.arrayListHandler: 将查询的结果,每一行先封装到Object数组中,然后将数据存入List集合
public static void arrayListHandler(){
QueryRunner qr = new QueryRunner();
String sql = "select * from student";
try {
Connection conn = JDBCUtils.getConnection();
List<Object[]> query = qr.query(conn, sql, new ArrayListHandler());
for(Object[] objs : query){
for (Object obj : objs){
System.out.print(obj+" ");
}
System.out.println();
DbUtils.closeQuietly(conn);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
3.BeanHandler: 将查询结果的第一行数据,封装到student对象
public static void BeanHandler(){
QueryRunner qr = new QueryRunner();
String sql = "select * from student";
try {
Connection conn = JDBCUtils.getConnection();
Student query = qr.query(conn, sql, new BeanHandler<Student>(Student.class));
System.out.println(query);
DbUtils.closeQuietly(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
4.BeanLIstHandler: 将查询结果的每一行封装到student对象,然后再存入List集合
public static void BeanListHandler(){
QueryRunner qr = new QueryRunner();
String sql = "select * from student";
try {
Connection conn = JDBCUtils.getConnection();
List<Student> query = qr.query(conn, sql, new BeanListHandler<Student>(Student.class));
for (Student student : query){
System.out.println(student+" ");
}
DbUtils.closeQuietly(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
5.ColumnListHandler:将查询结果的指定列的数据封装到List集合中
public static void ColumnListHandler(){
QueryRunner qr = new QueryRunner();
String sql = "select * from student";
try {
Connection conn = JDBCUtils.getConnection();
List<Object> sno = qr.query(conn, sql, new ColumnListHandler<>("sno"));
for (Object obj : sno)
System.out.println(obj);
DbUtils.closeQuietly(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
6.ScalarHanlder:将结果集第一行的某一列放到某个对象中
public static void ScalarHandler(){
QueryRunner qr = new QueryRunner();
String sql = "select count(*) from student";
try {
Connection conn = JDBCUtils.getConnection();
long query = qr.query(conn, sql, new ScalarHandler<Long>());
System.out.println(query);
DbUtils.closeQuietly(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
7.MapHandler:将结果集中的第一行数据封装到一个Map
public static void MapHandler(){
QueryRunner qr = new QueryRunner();
String sql = "select * from student where sno = ?";
try {
Connection conn = JDBCUtils.getConnection();
Map<String, Object> query = qr.query(conn, sql, new MapHandler(), 110);
System.out.println(query);
DbUtils.closeQuietly(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
8.MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
public static void MapListHandler() {
QueryRunner qr = new QueryRunner();
String sql = "select * from student where sno = ?";
try {
Connection conn = JDBCUtils.getConnection();
List<Map<String, Object>> query = qr.query(conn, sql, new MapListHandler(),110);
for (Map<String, Object> map : query) {
System.out.println(map);
}
DbUtils.closeQuietly(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
KeyedHandler:将结果集中的每一行数据都封装到一个Map里(List),再把这些map再存到一个map
public static void KeyedHandler(){
QueryRunner queryRunner = new QueryRunner();
String sql = “select * from student”;
Map<String,Map<String,Object>>map = null;
try {
Connection conn = JDBCUtils.getConnection();
map = queryRunner.query(conn,sql,new KeyedHandler(“sname”));
for(Map.Entry<String,Map<String,Object>> entry : map.entrySet()){
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
DbUtils.closeQuietly(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
DBUtils类
它提供关于关闭资源以及事务rollback,commit操作。里面的方法都是静态的。
跳转到目录
DBUtils工具
作用:简化JDBC的操作
DBUtils常用类与方法
QueryRunner 用来执行SQL语句对象
update(Connection conn, String sql, Object… params) 插入表记录、更新表记录、删除表记录
query(Connection conn, String sql, ResultSetHandler handler, Object… params) 查询表记录
ResultSetHandler 处理结果集的对象
BeanHandler:将结果集中第一条记录封装到一个指定的javaBean中。
BeanListHandler:将结果集中每一条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中
ScalarHandler:它是用于单数据。例如select count(*) from 表操作。
ColumnListHandler:将结果集中指定的列的字段值,封装到一个List集合中
public class Dbutils {
private static DruidDataSource dataSource;
@BeforeMethod
public void testBefore() throws IOException, ClassNotFoundException, SQLException {
Properties properties=new Properties();
properties.load(Dbutils.class.getResourceAsStream("/jdbc.properties"));
dataSource = new DruidDataSource();
dataSource.configFromPropety(properties);
}
@AllArgsConstructor
private static class InitRunnable implements Runnable {
private CountDownLatch countDownLatch;
@SneakyThrows
@Override
public void run() {
System.out.println(new Date());
Dbutils.insert();
countDownLatch.countDown();
}
}
@Test
public void curent() throws InterruptedException {
CountDownLatch countDownLatch=new CountDownLatch(1000);
List<Thread> workers = Stream
.generate(() -> new Thread(new InitRunnable(countDownLatch)))
.limit(1000)
.collect(toList());
workers.forEach(Thread::start);
countDownLatch.await();
}
public static void insert() throws Exception {
// 获取一个用来执行SQL语句对象
QueryRunner qr = new QueryRunner(dataSource);
String sql = "INSERT INTO stu(name, score) VALUES(?, ?)";
Object[] params = {"百岁山", "50"};
int count = qr.update(sql, params);
}
}