DBUtils 使用:
开发步骤
(1)copy jar包:
(2)核心类: QueryRunner类:
(3)使用核心类完成读写,以及批量操作:
写:
删除,
更新:
添加: 调用同一个方法: update()
package com.yidongxueyuan.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.SQLException;
import javax.sql.rowset.serial.SerialBlob;
import javax.sql.rowset.serial.SerialClob;
import javax.sql.rowset.serial.SerialException;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;
import com.yidongxueyuan.utils.C3P0Util;
public class QueryRunnerTest {
//修改: 添加
@Test
public void testUpdate() throws Exception {
//不考虑事务:
QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
int num = qr.update("insert into account (id, name, money) values(?,?,?)",new Object[]{1001,"王导演",250} );
System.out.println(num);
}
//删除操作:
@Test
public void testdelete() throws Exception {
//不考虑事务:
QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
int num = qr.update("delete from account where id=?",new Object[]{1001} );
System.out.println(num);
}
//修改: 自己完成:
//操作大数据: 大文本, 大字节:
//写入: 大文本
@Test
public void testBigText()throws IOException, SerialException, SQLException{
QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
String sql ="insert into t3 values(?,?)";
//使用流进行读取外部的文件;
File file = new File("C:\\Users\\Mrzhang\\Desktop\\分页.txt");
Reader reader = new FileReader(file);
//读取:
char chs []= new char[(int)file.length()];
reader.read(chs);//数据在字符数组当中:
//clob这是java当中提供的字符对象: SerialClob clob的是一个实现类:
Clob clob = new SerialClob(chs);
Object [] params = {2,clob};
qr.update(sql, params);
}
//写入大字节:
@Test
public void testBigBlob()throws IOException, SerialException, SQLException{
QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
String sql ="insert into t4 values(?,?)";
//使用流进行读取外部的文件;
File file = new File("C:\\Users\\Mrzhang\\Desktop\\01.png");
//字节流读取图片数据:
InputStream in = new FileInputStream(file);
byte b[]= new byte[(int)file.length()];
//clob这是java当中提供的字符对象: SerialClob clob的是一个实现类:
Blob blob = new SerialBlob(b);
Object [] params = {2,blob};
qr.update(sql, params);
}
//批量操作:
@Test
public void testbatch()throws IOException, SerialException, SQLException{
QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
String sql ="insert into account values(?,?,?)";
Object params [][]= new Object[10][];// 二维数组前面的【】: 记录的条数: 后面的【】是负责: ? 每条记录需要的参数的值:
for(int i=0 ; i< params.length ;i++){
params[i]= new Object[]{i+10,"王导演"+i,i+100.0};
}
//执行批量
qr.batch(sql, params); ///二维数组:
}
}
二: QueryRunner的查询操作:
query方法:
各种结果集处理器的使用:
关于处理器是个什么东西,就是各种集合或者javabean的处理器,哪种处理器就封装哪种类型的数据吧。我的理解
package com.yidongxueyuan.test;
import java.sql.Connection;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.KeyedHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.Test;
import com.yidongxueyuan.domain.Account;
import com.yidongxueyuan.utils.C3P0Util;
/*
* 测试结果处理器:
*/
public class TestResultSet {
private QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());//构造的时候,需要指定一个数据源:
@Test
//ArrayHandler 处理器, 只适应于一条结果的的情况, 将表当中的第一条数据封装到了一个Object[] 数组当中:
public void testDemo01() throws Exception {
Connection conn= null;
try {
// conn = C3P0Util.getConnection();
String sql = "select * from account"; //没有参数:
//查询操作:
Object[] objs = qr.query(sql, new ArrayHandler() );
System.out.println(Arrays.toString(objs));// [1, aaa, 800.0]
} catch (Exception e) {
// TODO: handle exception
}
}
// ArrayListHandler 适用于有多行的记录, 把每一条记录都封装到了不同的Object[]数组当中。 然后将Object数组放在list集合当中:
@Test
public void testDemo02() throws Exception {
Connection conn= null;
try {
String sql = "select * from account"; //没有参数:
//查询操作:
List<Object[]> list = qr.query(sql, new ArrayListHandler() );
System.out.println(list.size());//
} catch (Exception e) {
}
}
// BeanHandler, 适应于一条记录,将结果集封装了一个JavaBean当中: 没有指定查询具体的某一条记录, 查询表当中的第一条记录:
@Test
public void testDemo03() throws Exception {
Connection conn= null;
try {
String sql = "select * from account where id=? "; //没有参数:
//查询操作:
Account account =(Account) qr.query(sql, new BeanHandler(Account.class) ,10);
System.out.println(account);//
} catch (Exception e) {
}
}
// BeanListHandler 将每一条记录封装到了实体Bean,把这个实体bean存放在list 集合当中: List<Account>
@Test
public void testDemo04() throws Exception {
Connection conn= null;
try {
String sql = "select * from account "; //没有参数:
//查询操作:
List<Account> list = qr.query(sql, new BeanListHandler(Account.class));
System.out.println(list);//
for (Account account : list) {
System.out.println(account);
}
} catch (Exception e) {
}
}
@Test //ColumnListHandler 适合封装具体的某一列: List<Object >
public void testDemo05() throws Exception {
Connection conn= null;
try {
String sql = "select name from account "; //没有参数:
//查询操作:
List<Object> list = qr.query(sql, new ColumnListHandler("name"));
for (Object name : list) {
System.out.println(name);
}
} catch (Exception e) {
}
}
@Test //KeyedHandler 将查询的结构封装到了一个map集合当中: Map<keyName, Map<id, idvalue> >
public void testDemo06() throws Exception {
Connection conn= null;
try {
String sql = "select id,name from account "; //没有参数:
//查询操作:
Map<Object, Map<String, Object>> query = qr.query(sql, new KeyedHandler("name"));
//遍历:
for(Map.Entry<Object, Map<String, Object> > bme: query.entrySet() ){
System.out.println("====");
for (Map.Entry<String,Object> lme: bme.getValue().entrySet()) {
System.out.println(lme.getKey()+":::"+lme.getValue());
}
}
} catch (Exception e) {
}
}
//MapHandler 只适应于一条记录: Map<String, Object> stirng:列的名称: Object: 列的值: 默认值值查询第一条记录:
@Test
public void testDemo07() throws Exception {
Connection conn= null;
try {
String sql = "select * from account where id=?"; //没有参数:
//查询操作:
//列名 列的值:
Map<String, Object> query = qr.query(sql, new MapHandler(),10);
//遍历:
for (Map.Entry<String,Object> lme: query.entrySet()) {
System.out.println(lme.getKey()+":::"+lme.getValue());
}
} catch (Exception e) {
}
}
// MapListHandler 适合多条记录: List<Map<String, Object>>
@Test
public void testDemo08() throws Exception {
try {
String sql = "select * from account"; //没有参数:
//查询操作:
//列名 列的值:
List<Map<String, Object>> list = qr.query(sql, new MapListHandler());
//遍历:
for(Map<String,Object> map: list){
for (Map.Entry<String,Object> lme: map.entrySet()) {
System.out.println(lme.getKey()+":::"+lme.getValue());
}
}
} catch (Exception e) {
}
}
//ScalarHandler 适应于当行单列的结果集; select count(*) from tableName;
@Test
public void testDemo09() throws Exception {
try {
String sql = "select count(*) from account"; //没有参数:
//查询操作:
//列名 列的值:
Object count = qr.query(sql, new ScalarHandler());
System.out.println(count);
} catch (Exception e) {
}
}
}
三: QueryRunner 处理事务:
这里只放最后一个代码~
其他代码放在github上 ~ ~
https://gitee.com/wohaocai/query.
1: 事务: 操作单元:
2: 处理事务:
需求: 转账: 有事务的支持:
三个版本:
转账版本一:
QueryRunner 处理事务:
query(conn, sql, param);
query(conn, sql, param);
处理事务:
(1)构建QueryRunner对象的时候,没有必要指定数据源:
(2)执行具体方法的时候, 动态的传递一个conn对象:
这样保证了不同的方法使用的conn 对象是同一个对象。
既然是同一个conn 对象, 就可以保证多个操作处于同一个事务当中。
总结:
现在将业务方法定义在dao层: dao层定义数据库的访问方法, 不应该定义业务方法。
将业务方法定义在业务层,dao只定义增删改查的方法:
转账的 版本二:
优点: 将业务方法定义了业务service层:
dao层只定义了和数据库相关的增删改查的方法:
具体的操作:
dao层: 保证conn 的唯一: 采用注入的 方式: 有service层给dao层传递conn, 这样就保证了conn 的唯一:
弊端: service 层: 出现了Connection连接对象。 Connection对象是负责连接数据库的, 只能出现dao层, 不应该出现在service层。
版本三: 对象: 本地线程局部变量对象: ThreadLocal 本质上一个是一个map 集合:
原理:
public class ThreadLocal{
//存:
Map<Runnable,Object> map = new HashMap<Runnerable,Object>();
public Object put(Object obj){
map.set( obj);
return null;
}
//取 :
public Object get(Object obj){
return map.get()
}
//移除:
public Object remore(){
return map.remove();
}
}
总结: ThreadLocal这个类: 存放和取值的时候, key 都是本地线程:
案例: 测试ThreadLocal类:
版本三: 使用ThreadLocal 管理事务:
代码如下:dao层:
package com.yidongxueyuan.dao3;
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import com.yidongxueyuan.domain.Account;
public class DaoImpl implements Dao{
private Connection conn;
public DaoImpl (Connection conn){//注入:
this.conn = conn;
}
//依赖QueryRunner
private QueryRunner qr = new QueryRunner (); //不需要给出数据源:
@Override
public Account findByName(String name) {
String sql ="select * from account where name=?";
try {
Account account = qr.query(conn, sql, new BeanHandler<Account>(Account.class),name);
return account;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
@Override
public void updateAccount(Account account) {
String sql="update account set money = ? where name=?";
try {
qr.update(conn, sql, account.getMoney(),account.getName());
} catch (SQLException e) {
e.printStackTrace();
}
}
}
事务:
package com.yidongxueyuan.dao3;
import java.sql.Connection;
import javax.ejb.TransactionManagement;
import com.yidongxueyuan.dao2.Dao;
import com.yidongxueyuan.dao2.DaoImpl;
import com.yidongxueyuan.domain.Account;
import com.yidongxueyuan.utils.C3P0Util;
import com.yidongxueyuan.utils.TransactionManager;
/*
* 业务层: 定义具体的业务方法:
*/
public class TransFormer {
//定义业务方法:
public void transFormer(String SourceAccount,String targetAccount,float money) throws Exception{
Connection conn = TransactionManager.getConnection();
try {
Dao dao = new DaoImpl(conn);
TransactionManager.startTransaction();
//查询操作:
//来源账户:
Account sourceAcc = dao.findByName(SourceAccount);
sourceAcc.setMoney(sourceAcc.getMoney()-money);
//更新获取:
dao.updateAccount(sourceAcc);
//模拟异常的发生:
int num = 1/0;
//目标账户修改:更新回去:
Account targetAcc = dao.findByName(targetAccount);
targetAcc.setMoney(targetAcc.getMoney()+money);
dao.updateAccount(targetAcc);
} catch (Exception e) {
//异常发生:
TransactionManager.rollback();
} finally{
TransactionManager.commit();
//关闭资源:
TransactionManager.release();
}
}
}
测试:
package com.yidongxueyuan.dao3;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Before;
import org.junit.Test;
import com.yidongxueyuan.utils.C3P0Util;
public class TestTran {
private QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
@Before
public void before() throws Exception {
// 把数据还原:
qr.update("update account set money =1000 ");
}
@Test
public void testname() throws Exception {
TransFormer tf = new TransFormer();
tf.transFormer("aaa", "bbb", 100);
}
}