1. 增删改查 常用Handler处理器示例
QueryRunner类提供了两个构造方法:
•默认的构造方法
•需要一个 javax.sql.DataSource来作参数的构造方法。
public Object query(Connection conn, String sql, Object[] params, ResultSetHandler rsh) throws SQLException:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理PreparedStatement和ResultSet
的创建和关闭。
public Object query(String sql, Object[] params, ResultSetHandler rsh) throws SQLException: 几乎与第一种方法一样;唯一的不同在于它不将数据库连接提供给方法,并且它是从提供给构造方法的数据源(DataSource)或使用的setDataSource方法中重新获得Connection。
public Object query(Connection conn, String sql, ResultSetHandler rsh) throws SQLException :执行一个不需要置换参数的查询操作。
public int update(Connection conn, String sql, Object[] params) throws SQLException:用来执行一个更新(插入、更新或删除)操作。
public int update(Connection conn, String sql) throws SQLException:用来执行一个不需要置换参数的更新操作。
ResultSetHandler 接口的实现类
ArrayHandler:把结果集中的第一行数据转成对象数组。
ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
ColumnListHandler:将结果集中某一列的数据存放到List中。
KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,其key为指定的key。
MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
public class Demo1 { /** create database dbutils; use dbutils; create table user( id int primary key auto_increment, name varchar(40), password varchar(40), email varchar(60), birthday date ); insert into user(name,password,email,birthday) values('zs','123','xj@qq.com','1990-06-27'); insert into user(name,password,email,birthday) values('ls','123','xj@qq.com','1990-06-27'); insert into user(name,password,email,birthday) values('ww','123','xj@qq.com','1990-06-27'); * @throws SQLException */ @Test public void add() throws SQLException { //创建QueryRunner时带 连接池,获得的连接 用完后会自动归还到连接池 QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String sql = "insert into user(name,password,email,birthday) values(?,?,?,?)"; Object[] params = {"kevin", "12345", "xj@163.com", new Date()}; qr.update(sql, params); } @Test public void delete() throws SQLException { QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String sql = "delete from user where id=?"; qr.update(sql, 1); } @Test public void update() throws SQLException { QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String sql = "update user set name=? where id=?"; Object[] params = {"xiangjie", 2}; qr.update(sql, params); } @Test public void find() throws SQLException { QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String sql = "select * from user where id=?"; Object[] params = {2}; User user = (User) qr.query(sql, new BeanHandler(User.class), params); System.out.println(user.getName()); } @Test public void getAll() throws SQLException { QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String sql = "select * from user"; List list = (List) qr.query(sql, new BeanListHandler(User.class)); System.out.println(list.size()); } @Test public void testBatch() throws SQLException //SQL批处理 { QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String sql = "insert into user(name,password,email,birthday) values(?,?,?,?)"; Object[][] params = new Object[10][]; for(int i=0; i<10; i++) { params[i] = new Object[]{"xx"+i, "123456", "xj@qq.com", new Date()}; } qr.batch(sql, params); } // dbutils 存储大文本 (不建议使用,无缓存,文本被直接放到内存,很大文本直接用JDBC) /* create table testclob ( id int primary key auto_increment, resume text ); */ @Test public void testclob() throws IOException, SerialException, SQLException { QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String path = Demo1.class.getClassLoader().getResource("test.txt").getPath(); String sql = "insert into testclob(resume) values(?)"; FileReader in =new FileReader(path); char[] buffer = new char[(int) new File(path).length()]; in.read(buffer); SerialClob clob = new SerialClob(buffer); Object[] params = {clob}; qr.update(sql, params); } /* * dbutils 提供的 handler 处理器 */ @Test public void testArrayHandler() throws SQLException { QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String sql = "select * from user"; Object[] result = (Object[]) qr.query(sql, new ArrayHandler()); System.out.println(Arrays.asList(result)); } @Test public void testArrayListHandler() throws SQLException { QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String sql = "select * from user"; List<Object[]> list = (List<Object[]>) qr.query(sql, new ArrayListHandler()); for(Object[] obj : list) System.out.println(Arrays.asList(obj)); } @Test public void testKeyedHandler() throws SQLException { QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String sql = "select * from user"; Map<Integer, Map> map = (Map<Integer, Map>) qr.query(sql, new KeyedHandler("id")); for(Map.Entry<Integer, Map> me : map.entrySet()) { int id = me.getKey(); Map<String, Object> innermap = me.getValue(); for(Map.Entry<String , Object> innerme : innermap.entrySet() ) { String columnName = innerme.getKey(); Object value = innerme.getValue(); System.out.println(columnName + "=" + value); } System.out.println("-----------------"); } } @Test public void testMapHandler() throws SQLException { QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String sql = "select * from user"; Map<String, Object> map = (Map<String, Object>) qr.query(sql, new MapHandler()); for(Map.Entry<String , Object> entry : map.entrySet()) { System.out.println(entry.getKey() + "=" + entry.getValue()); } } @Test public void testMapListHandler() throws SQLException { QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String sql = "select * from user"; List<Map<String, Object>> list = (List<Map<String, Object>>) qr.query(sql, new MapListHandler()); for(Map<String, Object> map : list) { for(Map.Entry<String, Object> entry : map.entrySet()) { System.out.println(entry.getKey() + "=" + entry.getValue()); } System.out.println("------------------"); } } @Test public void testScalarHandler() throws SQLException { QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String sql = "select count(*) from user"; long L = (Long) qr.query(sql, new ScalarHandler(1)); int count = (int) L; System.out.println("count: " + count); } }
2. 事务操作
方式一: 能实现功能,但不实用
dao层 提供增删改查,共用一个connect
/* create table account( id int primary key auto_increment, name varchar(40), money float ); insert into account(name,money) values('aaa',1000); insert into account(name,money) values('bbb',1000); insert into account(name,money) values('ccc',1000); insert into account(name,money) values('ddd',1000); */ public class AccountDao { private Connection conn = null; public AccountDao(Connection conn) { this.conn = conn; } /* public void transfer() throws SQLException //不实用 { Connection conn = null; try { conn = JdbcUtils_C3P0.getConnection(); conn.setAutoCommit(false); QueryRunner qr = new QueryRunner(); String sql1 = "update account set money=money-100 where id=1"; String sql2 = "update account set money=money+100 where id=2"; qr.update(conn, sql1); qr.update(conn, sql2); conn.commit(); System.out.println("transfer success"); } catch (SQLException e) { conn.rollback(); e.printStackTrace(); }finally{ conn.close(); } } */ public void update(Account account) throws SQLException { QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String sql = "update account set name=?,money=? where id=?"; Object[] params = {account.getName(), account.getMoney(), account.getId()}; qr.update(conn, sql, params); } public Account find(int id) throws SQLException { QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String sql = "select * from account where id=?"; return (Account) qr.query(conn, sql, id, new BeanHandler(Account.class)); } }
Service层 提供transfer方法, 操作事务
public class AccountService { public void transfer(int sourceid, int targetid, float money) throws SQLException { Connection conn = null; try { conn = JdbcUtils_C3P0.getConnection(); conn.setAutoCommit(false); AccountDao dao = new AccountDao(conn); Account source = dao.find(sourceid); Account target = dao.find(targetid); source.setMoney(source.getMoney()-money); target.setMoney(target.getMoney()+money); dao.update(source); dao.update(target); conn.commit(); } catch (SQLException e) { if(conn!=null) conn.rollback(); }finally{ if(conn!=null) conn.close(); } } }
方式二: 利用ThreadLocal容器存储Connection, 实用方案
service层
public class AccountService { public void transfer(int sourceid, int targetid, float money) throws SQLException { try { JdbcUtils_C3P0.startTransaction(); //利用工具类, 开启事务 AccountDao dao = new AccountDao(); Account source = dao.find(sourceid); Account target = dao.find(targetid); source.setMoney(source.getMoney()-money); target.setMoney(target.getMoney()+money); dao.update(source); //int i=1/0; //制造异常中断 dao.update(target); JdbcUtils_C3P0.commit(); } catch (SQLException e) { e.printStackTrace(); JdbcUtils_C3P0.rollback(); //回滚 }finally{ JdbcUtils_C3P0.release(); //释放连接 } } }
Dao层
public class AccountDao { private Connection conn = null; public AccountDao(Connection conn) { this.conn = conn; } public AccountDao(){} public void update(Account account) throws SQLException { QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String sql = "update account set name=?,money=? where id=?"; Object[] params = {account.getName(), account.getMoney(), account.getId()}; qr.update(JdbcUtils_C3P0.getConnection(), sql, params); //利用工具类获得连接 } public Account find(int id) throws SQLException { QueryRunner qr = new QueryRunner(JdbcUtils_C3P0.getDataSource()); String sql = "select * from account where id=?"; return (Account) qr.query(JdbcUtils_C3P0.getConnection(), sql, id, new BeanHandler(Account.class)); } }
工具类:
public class JdbcUtils_C3P0 { private static ComboPooledDataSource ds = null; private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>(); //Threadlocal容器 static{ ds = new ComboPooledDataSource("c3p0config"); } public static Connection getConnection() throws SQLException{ Connection conn = threadLocal.get(); if(conn==null) { conn = getDataSource().getConnection(); threadLocal.set(conn); } return conn; } public static DataSource getDataSource() { return ds; } public static void startTransaction() { Connection conn = threadLocal.get(); try{ if(conn == null) { conn = getDataSource().getConnection(); threadLocal.set(conn); } conn.setAutoCommit(false); } catch(Exception e) { throw new RuntimeException(e); } } public static void rollback() { try { Connection conn = threadLocal.get(); if(conn!=null) conn.rollback(); } catch (Exception e) { throw new RuntimeException(e); } } public static void commit() { try { Connection conn = threadLocal.get(); if(conn!=null) conn.commit(); } catch (Exception e) { throw new RuntimeException(e); } } public static void release() { try { Connection conn = threadLocal.get(); if(conn!=null) { conn.close(); threadLocal.remove(); } } catch (Exception e) { throw new RuntimeException(e); } } }
工具类C3P0配置文档
<?xml version="1.0" encoding="UTF-8"?> <!-- c3p0-config.xml private static ComboPooledDataSource ds; static{ try { ds = new ComboPooledDataSource("c3p0config"); } catch (Exception e) { throw new ExceptionInInitializerError(e); } } --> <c3p0-config> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/transaction</property> <property name="user">root</property> <property name="password">123456</property> <property name="acquireIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">5</property> <property name="maxPoolSize">100</property> </default-config> <named-config name="c3p0config"> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/dbutils</property> <property name="user">root</property> <property name="password">123456</property> <property name="acquireIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">5</property> <property name="maxPoolSize">100</property><!-- intergalactoApp adopts a different approach to configuring statement caching --> </named-config> </c3p0-config>