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()方法,实现结果集的处理。

ArrayHandler和ArrayListHandler

1)创建chapter03数据库,然后再数据库中创建一个表users,

create database chapter03;
use chapter03;
create table user(
	id int(3) primary key auto_increment,
	name varchar(20) not null,
	password varchar(20) not null
);
insert into user(name,password) values('zhangsan','123456');
insert into user(name,password) values('lisi','123456');
insert into user(name,password) values('wangwu','123456');

2)引入DBUtils包,并编写java

在这里插入图片描述

BaseDao.java

package DBUtils;

import java.sql.*;
import org.apache.commons.dbutils.*;
import JDBC.JDBCUtils;

public class BaseDao {
	public static Object query(String sql,ResultSetHandler<?>rsh,Object...params)throws SQLException{
		Connection conn=null;
		PreparedStatement pstmt=null;
		ResultSet rs=null;
		try{
			conn=JDBCUtils.getConnection();
			pstmt=conn.prepareStatement(sql);
			if(params!=null){
				for(int i=0;i<params.length;++i){
					pstmt.setObject(i+1, params[i]);
				}
			}
			rs=pstmt.executeQuery();
			Object obj=rsh.handle(rs);
			return obj;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			JDBCUtils.release(rs, pstmt, conn);
		}
		return rs;
	}
}

ResultSetTest1.java

package DBUtils;

import java.sql.SQLException;
import org.apache.commons.dbutils.handlers.ArrayHandler;

public class ResultSetTest1 {
	public static void testArrayHandler()throws SQLException{
		BaseDao basedao=new BaseDao();
		String sql="select * from user where id=?";
		Object[] arr=(Object[]) basedao.query(sql, new ArrayHandler(), new Object[]{1});
		for(int i=0;i<arr.length;++i){
			System.out.print(arr[i]+",");
		}
	}
	public static void main(String[] args)throws SQLException{
		testArrayHandler();
	}
}

在这里插入图片描述
ResultSetTest2.java

package DBUtils;

import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.handlers.ArrayListHandler;

public class ResultSetTest2 {
	public static void testArrayHandler()throws SQLException{
		BaseDao basedao=new BaseDao();
		String sql="select * from user";
		List list=(List) basedao.query(sql, new ArrayListHandler());
		for(int i=0;i<list.size();++i){
			Object[] arr=(Object[])list.get(i);
			for(int j=0;j<arr.length;j++){
				System.out.print(arr[j]+",");
			}
			System.out.println();
		}
	}
	public static void main(String[] args)throws SQLException{
		testArrayHandler();
	}
}

在这里插入图片描述

BeanHandler、BeanListHandler和BeanMapHandler

这三个类是将结果集的数据封装到对应的JavaBean实例中,这也是实际开发中最常见的结果集处理方法。
User.java

package DBUtils;

public class User {
	private int id;
	private String name;
	private String password;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
}

ResultSetTest3 .java

package DBUtils;

import org.apache.commons.dbutils.handlers.*;
import java.sql.*;

public class ResultSetTest3 {
	public static void testBeanHandler()throws SQLException{
		BaseDao basedao=new BaseDao();
		String sql="select * from user where id=?";
		User user=(User)basedao.query(sql, new BeanHandler(User.class), 1);
		System.out.print("id为1的User对象的name值为:"+user.getName());
	}
	public static void main(String[] args)throws SQLException{
		testBeanHandler();
	}
}

在这里插入图片描述
ResultSetTest4.java

package DBUtils;

import org.apache.commons.dbutils.handlers.*;
import java.sql.*;
import java.util.ArrayList;

public class ResultSetTest4 {
	public static void testBeanListHandler()throws SQLException{
		String sql="select * from user";
		ArrayList<User>list=(ArrayList<User>)BaseDao.query(sql, new BeanListHandler(User.class));
		for(int i=0;i<list.size();++i){
			System.out.println("第"+(i+1)+"条数据的username值为:"+list.get(i).getName());
		}
	}
	public static void main(String[] args)throws SQLException{
		testBeanListHandler();
	}
}

在这里插入图片描述
ResultSetTest5.java

package DBUtils;

import java.sql.SQLException;
import java.util.Map;
import org.apache.commons.dbutils.handlers.BeanMapHandler;

public class ResultSetTest5 {
	public static void testBeanMapHandler()throws SQLException{
		String sql="select id,name,password from user";
		Map<Integer,User>map=(Map<Integer,User>)BaseDao.query(sql, new BeanMapHandler<Integer,User>(User.class,"id"));
		User u=map.get(1);
		String uName=u.getName();
		String uPassword=u.getPassword();
		System.out.print("id为1的User对象的name值为:"+uName+",password值为"+uPassword);
	}
	public static void main(String[] args)throws SQLException{
		testBeanMapHandler();
	}
}

在这里插入图片描述

MapHandler和MapListHandler

ResultSetTest6.java

package DBUtils;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.apache.commons.dbutils.handlers.*;

public class ResultSetTest6 {
	public static void testMapHandler()throws SQLException{
		BaseDao basedao=new BaseDao();
		String sql="select * from user where id=?";
		Map map=(Map)basedao.query(sql, new MapHandler(), 1);
		System.out.println(map);
	}
	public static void testMapListHandler()throws SQLException{
		BaseDao basedao=new BaseDao();
		String sql="select * from user";
		List list=(List)basedao.query(sql, new MapListHandler());
		System.out.println(list);
	}
	public static void main(String[] args)throws SQLException{
		//testMapHandler();
		testMapListHandler();
	}
}

在这里插入图片描述
在这里插入图片描述

ColumnListHandler

ResultSetTest7.java

package DBUtils;

import java.sql.SQLException;
import java.util.*;
import org.apache.commons.dbutils.handlers.*;

public class ResultSetTest7 {
	public static void testColumnListHandler()throws SQLException{
		BaseDao basedao=new BaseDao();
		String sql="select * from user";
		List list=(ArrayList<User>)basedao.query(sql, new ColumnListHandler("name"));
		System.out.println(list);
	}
	public static void main(String[] args)throws SQLException{
		testColumnListHandler();
	}
}

在这里插入图片描述

ScalarHandler

ResultSetTest8.java

package DBUtils;

import java.sql.SQLException;
import org.apache.commons.dbutils.handlers.*;

public class ResultSetTest8 {
	public static void testScalarHandler()throws SQLException{
		BaseDao basedao=new BaseDao();
		String sql="select * from user where id=?";
		Object arr=(Object)basedao.query(sql, new ScalarHandler("name"),1);
		System.out.println(arr);
	}
	public static void main(String[] args)throws SQLException{
		testScalarHandler();
	}
}

在这里插入图片描述

KeyedHandler

ResultSetTest9.java

package DBUtils;

import java.sql.SQLException;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.commons.dbutils.handlers.*;
import org.apache.commons.dbutils.QueryRunner;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class ResultSetTest9 {
	public static DataSource ds=null;
	static{
		ComboPooledDataSource cpds=new ComboPooledDataSource();
		ds=cpds;
	}
	public static void testKeyedHandler()throws SQLException{
		String sql="select id,name,password from user";
		QueryRunner qr=new QueryRunner(ds);
		Map<Object,Map<String,Object>>map=qr.query(sql, new KeyedHandler<Object>("id"));
		Map umap=(Map)map.get(new Integer(1));
		String uName=(String)umap.get("name");
		String uPassword=(String)umap.get("password");
		System.out.println(uName+":"+uPassword);
	}
	public static void main(String[] args)throws SQLException{
		testKeyedHandler();
	}
}

在这里插入图片描述

DBUtils实现增删改查

C3p0Utils.java

package DBUtils;

import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class C3p0Utils {
	private static DataSource ds;
	static{
		ds=new ComboPooledDataSource();
	}
	public static DataSource getDataSource(){
		return ds;
	}
}

DBUtilsDao.java

package DBUtils;

import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;
import JDBC.JDBCUtils;

public class DBUtilsDao {
	public List findAll()throws SQLException{
		QueryRunner runner=new QueryRunner(C3p0Utils.getDataSource());
		String sql="select * from user";
		List list=(List)runner.query(sql, new BeanListHandler(User.class));
		return list;
	}
	public User find(int id)throws SQLException{
		QueryRunner runner=new QueryRunner(C3p0Utils.getDataSource());
		String sql="select * from user where id=?";
		User user=(User)runner.query(sql, new BeanHandler(User.class),new Object[]{id});
		return user;
	}
	public Boolean insert(User user)throws SQLException{
		QueryRunner runner=new QueryRunner(C3p0Utils.getDataSource());
		String sql="insert into user(name,password)values(?,?)";
		int num=runner.update(sql, new Object[]{
				user.getName(),
				user.getPassword()
		});
		if(num>0){
			return true;
		}
		return false;
	}
	public Boolean update(User user)throws SQLException{
		QueryRunner runner=new QueryRunner(C3p0Utils.getDataSource());
		String sql="update user set name=?,password=? where id=?";
		int num=runner.update(sql, new Object[]{
				user.getName(),
				user.getPassword(),
				user.getId()
		});
		if(num>0)return true;
		return false;
	}
	public Boolean delete(int id)throws SQLException{
		QueryRunner runner=new QueryRunner(C3p0Utils.getDataSource());
		String sql="delete from user where id=?";
		int num=runner.update(sql, id);
		if(num>0)return true;
		return false;
	}
}

这样,就实现了用DBUtils框架对数据库的基本操作。需要注意的是,在查询方法中,用到了BeanHeadler和BeanListHeadler实现类来处理结果集,查询一条数据用的是能够处理一行数据的BeanHandler类,查询所有数据时用的是能处理所有行数据的BeanListHandler类,切勿使用错误,否则会造成程序报错。
增加功能
DBUtilsDaoTest1.java

package DBUtils;

import java.sql.SQLException;

public class DBUtilsDaoTest1 {
	private static DBUtilsDao dao=new DBUtilsDao();
	public static void testInsert() throws SQLException{
		User user=new User();
		user.setName("zhaoliu");
		user.setPassword("666666");
		boolean b=dao.insert(user);
		System.out.println(b);
	}
	public static void main(String[] args)throws SQLException{
		testInsert();
	}
}

在这里插入图片描述
在这里插入图片描述

修改功能
DBUtilsDaoTest2.java

package DBUtils;

import java.sql.SQLException;

public class DBUtilsDaoTest2 {
	private static DBUtilsDao dao=new DBUtilsDao();
	public static void testInsert() throws SQLException{
		User user=new User();
		user.setName("zhaoliu");
		user.setPassword("333333");
		user.setId(4);
		boolean b=dao.update(user);
		System.out.println(b);
	}
	public static void main(String[] args)throws SQLException{
		testInsert();
	}
}

在这里插入图片描述
在这里插入图片描述
删除功能
DBUtilsDaoTest3.java

package DBUtils;

import java.sql.SQLException;

public class DBUtilsDaoTest3 {
	private static DBUtilsDao dao=new DBUtilsDao();
	public static void testDelete() throws SQLException{
		boolean b=dao.delete(4);
		System.out.println(b);
	}
	public static void main(String[] args)throws SQLException{
		testDelete();
	}
}

在这里插入图片描述
在这里插入图片描述
查询功能
DBUtilsDaoTest4.java

package DBUtils;

import java.sql.SQLException;

public class DBUtilsDaoTest4 {
	private static DBUtilsDao dao=new DBUtilsDao();
	public static void testFind() throws SQLException{
		User user=dao.find(3);
		System.out.println(user.getId()+","+user.getName()+","+user.getPassword());;
	}
	public static void main(String[] args)throws SQLException{
		testFind();
	}
}

在这里插入图片描述

DBUtils处理事务

前面我们用DBUtils完成了对数据库增删改查的操作,其中使用了QueryRunner类中有参数的构造方法,参数即数据源,这时,框架会自动创建数据库连接,并释放连接。但这是处理一般操作的时候,当要进行事务操作时,连接的创建和释放就要由程序员自己实现了。
1)建立所需的数据库account作为账目记录表,并添加数据

use chapter03;
create table account(
	id int primary key auto_increment,
	name varchar(40),
	money float
);
insert into account(name,money)values('a',1000);
insert into account(name,money)values('b',2000);

在这里插入图片描述
2)创建实体类Account

package DBUtils;

public class Account {
	private int id;
	private String name;
	private float money;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public float getMoney() {
		return money;
	}
	public void setMoney(float money) {
		this.money = money;
	}
}

3)创建类JDBCUtils,该类封装了创建连接、开启事务、关闭事务等方法。需要注意的是,请求中的一个事务涉及多个数据库操作,如果这些操作中的Connection是从连接池获得的,两个DAO操作就要用到两个Connection,这样是没有办法完成一个事务的,因此需要借助ThreadLocal类。
ThreadLocal类的作用是在一个线程里记录变量。可以生成一个连接放在这个线程里,只要是这个线程的任何对象都可以共享这个连接,当线程结束后就删除这个连接。这样就保证了一个事务,一个连接、
JDBCUtils.java

package DBUtils;

import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class JDBCUtils {
	private static ThreadLocal<Connection> threadLocal=new ThreadLocal<Connection>();
	private static DataSource ds=new ComboPooledDataSource();
	public static DataSource getDataSource(){
		return ds;
	}
	public static Connection getConnection() throws SQLException{
		Connection conn=threadLocal.get();
		if(conn==null){
			conn=ds.getConnection();
			threadLocal.set(conn);
		}
		return conn;
	}
	public static void startTransaction(){
		try{
			Connection conn=getConnection();
			conn.setAutoCommit(false);
		}catch(SQLException e){
			e.printStackTrace();
		}
	}
	public static void commit(){
		try{
			Connection conn=threadLocal.get();
			if(conn!=null)conn.commit();
		}catch(SQLException e){
			e.printStackTrace();
		}
	}
	public static void rollback(){
		try{
			Connection conn=threadLocal.get();
			if(conn!=null)conn.rollback();
		}catch(SQLException e){
			e.printStackTrace();
		}
	}
	public static void close(){
		Connection conn=threadLocal.get();
		if(conn!=null){
			try{
				conn.close();
			}catch(SQLException e){
				e.printStackTrace();
			}finally{
				threadLocal.remove();
				conn=null;
			}
		}
	}
}

4)创建类AccountDao,该类封装了转账所需的数据库操作,包括查询用户,转入,转出操作。
AccountDao.java

package DBUtils;

import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;

public class AccountDao {
	public Account find(String name)throws SQLException{
		QueryRunner runner=new QueryRunner();
		Connection conn=JDBCUtils.getConnection();
		String sql="select * from account where name=?";
		Account account=(Account)runner.query(conn, sql, new BeanHandler(Account.class),new Object[]{name});
		return account;
	}
	public void update(Account account)throws SQLException{
		QueryRunner runner=new QueryRunner(C3p0Utils.getDataSource());
		Connection conn=JDBCUtils.getConnection();
		String sql="update account set money=? where name=?";
		runner.update(conn,sql,new Object[]{account.getMoney(),account.getName()});
	}
}

5)创建类Business,该类包括转账过程的逻辑方法,导入了封装事务操作的JDBCUtils类和封装数据库操作的AccountDao类,完成转账操作。
Business.java

package DBUtils;

import java.sql.SQLException;

public class Business {
	public static void transfer(String sourceAccountName,String toAccountName,float money){
		try{
			JDBCUtils.startTransaction();
			AccountDao dao=new AccountDao();
			Account accountFrom=dao.find(sourceAccountName);
			Account accountto=dao.find(toAccountName);
			if(money<accountFrom.getMoney()){
				accountFrom.setMoney(accountFrom.getMoney()-money);
			}else{
				System.out.println("转出账户余额不足");
			}
			accountto.setMoney(accountto.getMoney()+money);
			dao.update(accountFrom);
			dao.update(accountto);
			JDBCUtils.commit();
			System.out.print("提交成功");
		}catch(SQLException e){
			System.out.println("提交失败");
			JDBCUtils.rollback();
			e.printStackTrace();
		}finally{
			JDBCUtils.close();
		}
	}
	public static void main(String[] args)throws SQLException{
		transfer("a","b",200);
	}
}

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值