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>