對於數據庫的增刪改查等操作已經有框架實現了
DBUtils是java編程中的數據庫操作實用工具,小巧簡單實用。DBUtils封裝了對JDBC的操作,簡化了JDBC操作。可以少寫代碼。
- 對於數據表的讀操作,他可以把結果轉換成List,Array,Set等java集合,便於程序員操作
- 對於數據表的寫操作,也變得很簡單(只需寫sql語句)
- 可以使用數據源,使用JNDI,數據庫連接池等技術來優化性能–重用已經構建好的數據庫連接對象
DBUtils的三個核心對象
- QueryRunner類
- ResultSetHandler接口
- DBUtils類
一、QueryRunner類:QueryRunner中提供對sql語句操作的API.
它主要有三個方法
- query() 用於執行select
- update() 用於執行insert update delete
- batch() 批處理
二、ResultSetHandler接口:用於定義select操作後,怎樣封裝結果集.
三、DbUtils類:它就是一個工具類,定義了關閉資源與事務處理的方法
Dbutils快速入門
導入jar包
創建QueryRunner對象
使用query方法執行select語句
使用ResultSetHandler封裝結果集
使用DbUtils類釋放資源
一、導入jar包
commons-dbutils-1.4.jar,還有mysql的連接驅動,C3P0的jar包
二、創建QueryRunner對象
QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
三、使用相關方法
QueryRunner對象
QueryRunnerAPI
一、構造函數:
- new QueryRunner(); 它的事務可以手動控制。
也就是說此對象調用的方法(如:query、update、batrch)參數中要有Connection對象。 - new QueryRunner(DataSource ds); 它的事務是自動控制的。一個sql一個事務。
此對象調用的方法(如:query、update、batrch)參數中無需Connection對象。
二、方法:
首先附上C3P0util.java
package com.yanglin.utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* Created by zeroyoung on 2016/10/29.
*/
public class C3POUtils {
public static DataSource dataSource = new ComboPooledDataSource();
public static DataSource getDataSource(){
return dataSource;
}
public static Connection getConnection(){
try {
return dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("創建連接失敗!");
}
}
public static void close(ResultSet rs, Statement st, Connection conn){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
使用dbutls包測試CRUD操作:
@Test
public void testInsert(){
DataSource dataSource = C3POUtils.getDataSource();
QueryRunner qr = new QueryRunner(dataSource);
try {
int i = qr.update("insert into users(NAME,PASSWORD,email,birthday)values(?,?,?,?)", "tom", "123", "[email protected]", new Date());
System.out.println(i);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void testupdate(){
DataSource dataSource = C3POUtils.getDataSource();
QueryRunner qr = new QueryRunner(dataSource);
try {
int i = qr.update("update users set NAME=? where id=?", "sss", 4);
System.out.println(i);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void testDelete() throws SQLException{
//創建一個QueryRunner對象
QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
qr.update("delete from users where id=?", 4);
}
@Test//批處理,插入多條數據
public void testBatch() throws SQLException{
//創建一個QueryRunner對象
QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
Object[][] params = new Object[10][];//高維代表執行多少次sql語句
for (int i = 0; i < params.length; i++) {
params[i] = new Object[]{"丟丟"+i,"123","[email protected]",new Date()};//給每次執行的sql語句中的?賦值
}
qr.batch("insert into users(NAME,PASSWORD,email,birthday) values(?,?,?,?)", params );
}
ResultSetHandler接口
ResultSetHandler下的所有結果處理器
- ArrayHandler:適合取1條記錄。把該條記錄的每列值封裝到一個數組中Object[]
- ArrayListHandler:適合取多條記錄。把每條記錄的每列值封裝到一個數組中Object[],把數組封裝到一個List中
- ColumnListHandler:取某一列的數據。封裝到List中。
- KeyedHandler:取多條記錄,每一條記錄封裝到一個Map中,再把這個Map封裝到另外一個Map中,key爲指定的字段值。
- MapHandler:適合取1條記錄。把當前記錄的列名和列值放到一個Map中
- MapListHandler:適合取多條記錄。把每條記錄封裝到一個Map中,再把Map封裝到List中
- ScalarHandler:適合取單行單列數據
- BeanHandler:取出一條記錄,封裝到一個bean中
- BeanListHandler :取出多條記錄,分別分裝到bean當中
測試代碼:
@Test//ArrayHandler:適合取1條記錄。把該條記錄的每列值封裝到一個數組中Object[]
public void teseArrayHandler() throws SQLException{
QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
Object[] arr = qr.query("select * from users", new ArrayHandler());
for (Object o : arr) {
System.out.println(o);
}
}
@Test//ArrayListHandler:適合取多條記錄。把每條記錄的每列值封裝到一個數組中Object[],把數組封裝到一個List中
public void testArrayListHandler() throws SQLException{
QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
List<Object[]> list = qr.query("select * from users", new ArrayListHandler());
for (Object[] o : list) {
for (Object os:o) {
System.out.println(os);
}
System.out.println();
}
}
@Test//ColumnListHandler:取某一列的數據。封裝到List中。
public void testColumnListHandlerr() throws SQLException{
QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
List<Object> list = qr.query("select * from users", new ColumnListHandler(2));
for (Object o : list) {
System.out.println(o);
}
}
@Test//KeyedHandler:取多條記錄,每一條記錄封裝到一個Map中,再把這個Map封裝到另外一個Map中,key爲指定的字段值。
public void testKeyedHandler() throws SQLException{
QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
Map<Object, Map<String, Object>> map = qr.query("select * from users", new KeyedHandler());
for (Map.Entry<Object,Map<String, Object>> m: map.entrySet()) {
System.out.println(m.getKey());
for (Map.Entry<String,Object> mm: m.getValue().entrySet()) {
System.out.println(mm.getKey()+"------"+mm.getValue());
}
System.out.println("------------------");
}
}
@Test//MapHandler:適合取1條記錄。把當前記錄的列名和列值放到一個Map中
public void testMapHandler() throws SQLException{
QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
Map<String, Object> map = qr.query("select * from users", new MapHandler());
for (Map.Entry<String,Object> m: map.entrySet()) {
System.out.println(m.getKey()+"--------------------"+m.getValue());
}
}
@Test//MapListHandler:適合取多條記錄。把每條記錄封裝到一個Map中,再把Map封裝到List中
public void testMapListHandler() throws SQLException{
QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
List<Map<String,Object>> list = qr.query("select * from users", new MapListHandler());
for (Map<String, Object> map : list) {
for (Map.Entry<String, Object> m : map.entrySet()) {
System.out.println(m.getKey()+"\t"+m.getValue());
}
System.out.println("---------------");
}
}
@Test //ScalarHandler:適合取單行單列數據
public void testScalarHandler() throws SQLException{
QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
Object o = qr.query("select count(*) from users", new ScalarHandler(1));
System.out.println(o);//long類型的
}
@Test //BeanHandler:適合取單行數據封裝到User對象當中,取不到,不會報錯,會返回空
public void testBeanHandler() throws SQLException{
QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
User user = qr.query("select * from users where id=?", new BeanHandler<User>(User.class),1);
System.out.println(user);
}
@Test //BeanListHandler:取出一個多條記錄封裝到每一個User當中,返回list
public void testBeanListHandler() throws SQLException{
QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
//List<User> list = qr.query("select * from users where id=?", new BeanListHandler<User>(User.class),1);
List<User> list = qr.query("select * from users ", new BeanListHandler<User>(User.class));
System.out.println(list.size());
}
DBUtils控制事務
當我們需要控制事務的時候,我們就得調用相關帶有Connection的query(),update()等方法了。但是調用事務我們需要一個Connection對象,這個對象的。然而我們在dao的實現曾是這樣的
DataSource dataSource = C3POUtils.getDataSource();
QueryRunner qr = new QueryRunner(dataSource);
雖然我們的C3P0utils當中有getConnection()方法可以得到一個Connection對象,但是我們事務的開啓都是在service當中的。dao層的值提供數據庫的增刪改查等操作,不涉及業務邏輯層。
而且我們也不能在service當中調用C3POUitls,因爲服務不涉及數據庫相關的操作。而且也會有線程安全問題。
這個時候,我們就得需要使用ThreadLocal這個類的
ThreadLocal類簡單來說就是一個線程局部變量,他可以在線程當中存放局部變量,調用該類的get方法,永遠返回當前線程放入的數據。線程局部變量。
package com.yanglin.utils;
import java.sql.Connection;
import java.sql.SQLException;
/**
* Created by zeroyoung on 2016/10/30.
*/
public class ManagerThreadLocal {
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
public static Connection getConnection(){
Connection conn = tl.get();
if(conn==null){
conn = C3POUtils.getConnection();
tl.set(conn);
}
return conn;
}
/**
* 開始事務
*/
public static void BeginTransaction(){
try {
getConnection().setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
/*
* 提交事務
* */
public static void commit(){
try {
getConnection().commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
/*
* 回滾
* */
public static void rollback(){
try {
getConnection().rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
/*
* 釋放資源
* */
public static void close(){
try {
getConnection().close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
測試使用:
public class AccountDaoImpl implements AccountDao {
public void updateAccount(String fromname, String toname, double money) throws Exception {
//創建一個QueryRunner對象
QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
qr.update("update account set money=money-? where name=?",money,fromname);
qr.update("update account set money=money+? where name=?",money,toname);
}
public void updateAccout(Account account) throws Exception {
QueryRunner qr = new QueryRunner();
qr.update(ManagerThreadLocal.getConnection(),"update account set money=? where name=?",account.getMoney(),account.getName());
}
public Account findAccountByName(String name) throws Exception {
QueryRunner qr = new QueryRunner();
return qr.query(ManagerThreadLocal.getConnection(),"select * from account where name=?", new BeanHandler<Account>(Account.class),name);
}
}