1、利用BeanUtils的前提得要加入以下兩個jar包:
commons-beanutils-1.8.0.jar
commons-logging-1.1.1.jar
package com.shellway.jdbcDAO;import java.util.List;import org.junit.Test;public class TestDAO { DAO dao = new DAO(); @Test public void testUpdate() throws Exception { String sql = "update examstudent set grade=? where flow_id=12345"; dao.update(sql, 88); } @Test public void test() throws Exception { String sql = "select flow_id flowID,type,id_card idCard, " + "exam_card examCard,student_name studentName,location,grade " + "from examstudent where flow_id = ? "; Student stu = dao.get(Student.class, sql, 12345); System.out.PRintln(stu); } @Test public void testGetSome() throws Exception { String sql = "select flow_id flowID,type,id_card idCard, " + "exam_card examCard,student_name studentName,location,grade " + "from examstudent"; List<Student> students = dao.getForList(Student.class, sql); System.out.println(students); } @Test public void testGetForValue() throws Exception { String sql = "select grade from examstudent where flow_id = ? "; Object obj = dao.getforvalue(sql, 123456); System.out.println(obj); }}測試類
package com.shellway.jdbcDAO;import java.sql.Connection;import java.sql.ResultSet;import java.sql.PreparedStatement;import java.sql.ResultSetMetaData;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import org.apache.commons.beanutils.BeanUtils;public class DAO { public void update(String sql, Object... args) throws Exception { Connection conn = null; PreparedStatement ps = null; try { conn = JDBCTools.getConnection(); ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.release(null, ps, conn); } } // 獲取一個對象通用的方法 public <T> T get(Class<T> clazz, String sql, Object... args) throws Exception { T entity = null; Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCTools.getConnection(); ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } rs = ps.executeQuery(); ResultSetMetaData rsmd = rs.getMetaData(); Map<String, Object> map = null; while (rs.next()) { map = new HashMap<String, Object>(); for (int i = 0; i < rsmd.getColumnCount(); i++) { String columnLabel = rsmd.getColumnLabel(i + 1); Object columnValue = rs.getObject(i + 1); map.put(columnLabel, columnValue); } if (map.size() > 0) { entity = clazz.newInstance(); for (Map.Entry<String, Object> entry : map.entrySet()) { String label = entry.getKey(); Object value = entry.getValue(); BeanUtils.setProperty(entity, label, value); } } } } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.release(rs, ps, conn); } return entity; } // 獲取一組對象通用的方法 public <T> List<T> getForList(Class<T> clazz, String sql, Object... args) throws Exception { T entity = null; Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; List<T> result = new ArrayList<T>(); try { conn = JDBCTools.getConnection(); ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } rs = ps.executeQuery(); ResultSetMetaData rsmd = rs.getMetaData(); List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); Map<String, Object> map = new HashMap<String, Object>(); while (rs.next()) { for (int i = 0; i < rsmd.getColumnCount(); i++) { String columnLabel = rsmd.getColumnLabel(i + 1); Object columnValue = rs.getObject(i + 1); map.put(columnLabel, columnValue); } list.add(map); if (list.size() > 0) { entity = clazz.newInstance(); for (Map<String, Object> ll : list) { for (Map.Entry<String, Object> entry : ll.entrySet()) { String label = entry.getKey(); Object value = entry.getValue(); BeanUtils.setProperty(entity, label, value); } } result.add(entity); } } } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.release(rs, ps, conn); } return result; } // 獲取一個對象中一列的值通用的方法 public <E> E getforvalue(String sql, Object... args) throws Exception { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCTools.getConnection(); ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } rs = ps.executeQuery(); if (rs.next()) { return (E) rs.getObject(1); } } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.release(rs, ps, conn); } return null; }}通用的DAO.java
package com.shellway.jdbcDAO;import java.io.InputStream;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.sql.Statement;import java.util.HashMap;import java.util.Map;import java.util.Properties;import java.sql.PreparedStatement;public class JDBCTools { public static <T> T get(Class<T> clazz, String sql, Object... args) throws Exception { T entity = null; Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCTools.getConnection(); ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } rs = ps.executeQuery(); ResultSetMetaData rsmd = rs.getMetaData(); Map<String, Object> map = new HashMap<String, Object>(); while (rs.next()) { for (int i = 0; i < rsmd.getColumnCount(); i++) { String columnLabel = rsmd.getColumnLabel(i + 1); Object columnValue = rs.getObject(i + 1); // Object columnValue = rs.getObject(columnLabel); map.put(columnLabel, columnValue); } } if (map.size() > 0) { entity = clazz.newInstance(); for (Map.Entry<String, Object> values : map.entrySet()) { String key = values.getKey(); Object value = values.getValue(); ReflectionUtils.setFieldValue(entity, key, value); } } } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.release(rs, ps, conn); } return entity; } public static void update(String sql, Object... args) throws Exception { Connection conn = null; PreparedStatement ps = null; try { conn = JDBCTools.getConnection(); ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } System.out.println(sql); ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.release(null, ps, conn); } } public static Connection getConnection() throws Exception { Properties proper = new Properties(); InputStream in = JDBCTools.class.getClassLoader().getResourceAsStream( "jdbc.properties"); proper.load(in); String driverClass = proper.getProperty("driver"); String jdbcUrl = proper.getProperty("jdbcUrl"); String user = proper.getProperty("user"); String passWord = proper.getProperty("password"); Class.forName(driverClass); Connection connection = DriverManager.getConnection(jdbcUrl, user, password); return connection; } public static void release(ResultSet rs, Statement state, Connection conn) throws Exception { if (rs != null) { try { rs.close(); } catch (Exception e) { e.printStackTrace(); } } if (state != null) { try { state.close(); } catch (Exception e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (Exception e) { e.printStackTrace(); } } }}JDBCTools工具類
driver=com.MySQL.jdbc.DriverjdbcUrl=jdbc:mysql://localhost:3306/testuser=rootpassword=123配置文件jdbc.properties
package com.shellway.jdbc;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;/** * 反射的 Utils 函數集合 提供訪問私有變量, 獲取泛型類型 Class, 提取集合中元素屬性等 Utils 函數 * * @author Administrator * */public class ReflectionUtils { /** * 通過反射, 獲得定義 Class 時聲明的父類的泛型參數的類型 如: public EmployeeDao extends * BaseDao<Employee, String> * * @param clazz * @param index * @return */ @SuppressWarnings("unchecked") public static Class getSuperClassGenricType(Class clazz, int index) { Type genType = clazz.getGenericSuperclass(); if (!(genType instanceof ParameterizedType)) { return Object.class; } Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); if (index >= params.length || index < 0) { return Object.class; } if (!(params[index] instanceof Class)) { return Object.class; } return (Class) params[index]; } /** * 通過反射, 獲得 Class 定義中聲明的父類的泛型參數類型 如: public EmployeeDao extends * BaseDao<Employee, String> * * @param <T> * @param clazz * @return */ @SuppressWarnings("unchecked") public static <T> Class<T> getSuperGenericType(Class clazz) { return getSuperClassGenricType(clazz, 0); } /** * 循環向上轉型, 獲取對象的 DeclaredMethod * * @param object * @param methodName * @param parameterTypes * @return */ public static Method getDeclaredMethod(Object object, String methodName, Class<?>[] parameterTypes) { for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass .getSuperclass()) { try { // superClass.getMethod(methodName, parameterTypes); return superClass.getDeclaredMethod(methodName, parameterTypes); } catch (NoSuchMethodException e) { // Method 不在當前類定義, 繼續向上轉型 } // .. } return null; } /** * 使 filed 變為可訪問 * * @param field */ public static void makeaccessible(Field field) { if (!Modifier.isPublic(field.getModifiers())) { field.setAccessible(true); } } /** * 循環向上轉型, 獲取對象的 DeclaredField * * @param object * @param filedName * @return */ public static Field getDeclaredField(Object object, String filedName) { for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass .getSuperclass()) { try { return superClass.getDeclaredField(filedName); } catch (NoSuchFieldException e) { // Field 不在當前類定義, 繼續向上轉型 } } return null; } /** * 直接調用對象方法, 而忽略修飾符(private, protected) * * @param object * @param methodName * @param parameterTypes * @param parameters * @return * @throws InvocationTargetException * @throws IllegalArgumentException */ public static Object invokeMethod(Object object, String methodName, Class<?>[] parameterTypes, Object[] parameters) throws InvocationTargetException { Method method = getDeclaredMethod(object, methodName, parameterTypes); if (method == null) { throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + object + "]"); } method.setAccessible(true); try { return method.invoke(object, parameters); } catch (IllegalAccessException e) { System.out.println("不可能拋出的異常"); } return null; } /** * 直接設置對象屬性值, 忽略 private/protected 修飾符, 也不經過 setter * * @param object * @param fieldName * @param value */ public static void setFieldValue(Object object, String fieldName, Object value) { Field field = getDeclaredField(object, fieldName); if (field == null) throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]"); makeAccessible(field); try { field.set(object, value); } catch (IllegalAccessException e) { System.out.println("不可能拋出的異常"); } } /** * 直接讀取對象的屬性值, 忽略 private/protected 修飾符, 也不經過 getter * * @param object * @param fieldName * @return */ public static Object getFieldValue(Object object, String fieldName) { Field field = getDeclaredField(object, fieldName); if (field == null) throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]"); makeAccessible(field); Object result = null; try { result = field.get(object); } catch (IllegalAccessException e) { System.out.println("不可能拋出的異常"); } return result; }}反射工具類:ReflectionUtils.java 也可通過它代替BeanUtils的setProperty()給對象賦值然后返回該對象
2、獲取數據庫中的一些元數據:
@Test public void testDatebaseMetaData() throws Exception { Connection conn = null; ResultSet rs = null; try { conn = JDBCTools.getConnection(); DatabaseMetaData dbmd = conn.getMetaData(); // 得到數據庫的一些基本信息 int version = dbmd.getDatabaseMajorVersion(); System.out.println(version); String user = dbmd.getUserName(); System.out.println(user); rs = dbmd.getCatalogs(); while (rs.next()) { String str = rs.getString(1); System.out.println(str); } } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.release(rs, null, conn); } }通過DatabaseMetaData dbmd = conn.getMetaData();獲取
3、獲取插入記錄的主鍵值,在加入購物車時用到:
@Test public void testPrimeryKey() throws Exception { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; String sql = "insert into customer(name,email,birth) values(?,?,?) "; try { conn = JDBCTools.getConnection(); ps = conn.prepareStatement(sql, ps.RETURN_GENERATED_KEYS); ps.setString(1, "BBBB"); ps.setString(2, "BBBB@163.COM"); ps.setDate(3, new Date(new java.util.Date().getTime())); ps.executeUpdate(); rs = ps.getGeneratedKeys(); if (rs.next()) { Object obj = rs.getObject(1); System.out.println(obj); } } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.release(null, ps, conn); } }獲取最新插入記錄的主鍵值
4、讀取 blob 數據: 1. 使用 getBlob 方法讀取到 Blob 對象2. 調用 Blob 的 getBinaryStream() 方法得到輸入流。再使用 IO 操作即可.
@Test public void readBlob(){ Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection = JDBCTools.getConnection(); String sql = "SELECT id, name customerName, email, birth, picture " + "FROM customers WHERE id = 13"; preparedStatement = connection.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); if(resultSet.next()){ int id = resultSet.getInt(1); String name = resultSet.getString(2); String email = resultSet.getString(3); System.out.println(id + ", " + name + ", " + email); Blob picture = resultSet.getBlob(5); InputStream in = picture.getBinaryStream(); System.out.println(in.available()); OutputStream out = new FileOutputStream("flower.jpg"); byte [] buffer = new byte[1024]; int len = 0; while((len = in.read(buffer)) != -1){ out.write(buffer, 0, len); } in.close(); out.close(); } } catch (Exception e) { e.printStackTrace(); } finally{ JDBCTools.releaseDB(resultSet, preparedStatement, connection); } }讀取Blob數據(如圖片)
5、事務:
• 事務:指構成單個邏輯工作單元的操作集合• 事務處理:保證所有事務都作為一個工作單元來執行,即使出現了故障,都不能改變這種執行方式。當在一個事務中執行多個操作時,要么所有的事務都被提交(commit),要么整個事務回滾(rollback)到最初狀態• 當一個連接對象被創建時,默認情況下是自動提交事務:每次執行一個 SQL 語句時,如果執行成功,就會向數據庫自動提交,而不能回滾• 為了讓多個 SQL 語句作為一個事務執行:––調用 Connection 對象的 setAutoCommit(false); 以取消自動提交事務––在所有的 SQL 語句都成功執行后,調用 commit(); 方法提交事務––在出現異常時,調用 rollback(); 方法回滾事務––若此時 Connection 沒有被關閉, 則需要恢復其自動提交狀態。數據庫的隔離級別:• 對于同時運行的多個事務, 當這些事務訪問數據庫中相同的數據時, 如果沒有采取必要的隔離機制, 就會導致各種并發問題:–––臟讀: 對于兩個事物 T1, T2, T1 讀取了已經被 T2 更新但還沒有被提交的字段. 之后, 若 T2 回滾, T1讀取的內容就是臨時且無效的.–––不可重復讀: 對于兩個事物 T1, T2, T1 讀取了一個字段, 然后 T2 更新了該字段. 之后,T1再次讀取同一個字段, 值就不同了.–––幻讀: 對于兩個事物 T1, T2, T1 從一個表中讀取了一個字段, 然后 T2 在該表中插入了一些新的行. 之后, 如果 T1 再次讀取同一個表, 就會多出幾行.• 數據庫事務的隔離性: 數據庫系統必須具有隔離并發運行各個事務的能力, 使它們不會相互影響, 避免各種并發問題.• 一個事務與其他事務隔離的程度稱為隔離級別. 數據庫規定了多種事務隔離級別, 不同隔離級別對應不同的 干擾程度,隔離級別越高, 數據一致性就越好, 但并發性越弱.關于事務: 1. 如果多個操作, 每個操作使用的是自己的單獨的連接, 則無法保證事務.2. 具體步驟: 1). 事務操作開始前, 開始事務:取消Connection 的默認提交行為. connection.setAutoCommit(false). 2). 如果事務的操作都成功,則提交事務: connection.commit(); 3). 回滾事務: 若出現異常, 則在 catch 塊中回滾事務:connection.rollback();
@Test public void testTransaction() { Connection connection = null; try { connection = JDBCTools.getConnection(); System.out.println(connection.getAutoCommit()); // 開始事務: 取消默認提交. connection.setAutoCommit(false); String sql = "UPDATE users SET balance = " + "balance - 500 WHERE id = 1"; update(connection, sql); int i = 10 / 0; System.out.println(i); sql = "UPDATE users SET balance = " + "balance + 500 WHERE id = 2"; update(connection, sql); // 提交事務 connection.commit(); } catch (Exception e) { e.printStackTrace(); // 回滾事務 try { connection.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } } finally { JDBCTools.releaseDB(null, null, connection); } /* * try { * * //開始事務: 取消默認提交. connection.setAutoCommit(false); * * //... * * //提交事務 connection.commit(); } catch (Exception e) { //... * * //回滾事務 try { connection.rollback(); } catch (SQLException e1) { * e1.printStackTrace(); } } finally{ JDBCTools.releaseDB(null, null, * connection); } */ // DAO dao = new DAO(); // // String sql = "UPDATE users SET balance = " + // "balance - 500 WHERE id = 1"; // dao.update(sql); // // int i = 10 / 0; // System.out.println(i); // // sql = "UPDATE users SET balance = " + // "balance + 500 WHERE id = 2"; // dao.update(sql); }事務測試例子
@Test public void testTransactionIsolationRead() { String sql = "SELECT balance FROM users WHERE id = 1"; Integer balance = getForValue(sql); System.out.println(balance); } // 返回某條記錄的某一個字段的值 或 一個統計的值(一共有多少條記錄等.) public <E> E getForValue(String sql, Object... args) { // 1. 得到結果集: 該結果集應該只有一行, 且只有一列 Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { // 1. 得到結果集 connection = JDBCTools.getConnection(); System.out.println(connection.getTransactionIsolation()); // connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED); connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < args.length; i++) { preparedStatement.setObject(i + 1, args[i]); } resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { return (E) resultSet.getObject(1); } } catch (Exception ex) { ex.printStackTrace(); } finally { JDBCTools.releaseDB(resultSet, preparedStatement, connection); } // 2. 取得結果 return null; }事務的隔離級別:在 JDBC 程序中可以通過 Connection 的 setTransactionIsolation 來設置事務的隔離級別
6、批量處理JDBC語句提高處理速度:
• 當需要成批插入或者更新記錄時??梢圆捎肑ava的批量更新機制, 這一機制允許多條語句一次性提交給數據庫批量處理。通常情況下比單獨提交處理更有效率• JDBC的批量處理語句包括下面兩個方法: –addBatch(String):添加需要批量處理的SQL語句或是參數; –executeBatch(): 執行批量處理語句;• 通常我們會遇到兩種批量執行SQL語句的情況: – 多條SQL語句的批量處理; – 一個SQL語句的批量傳參;@Test public void testBatch(){ Connection connection = null; PreparedStatement preparedStatement = null; String sql = null; try { connection = JDBCTools.getConnection(); JDBCTools.beginTx(connection); sql = "INSERT INTO customers VALUES(?,?,?)"; preparedStatement = connection.prepareStatement(sql); Date date = new Date(new java.util.Date().getTime()); long begin = System.currentTimeMillis(); for(int i = 0; i < 100000; i++){ preparedStatement.setInt(1, i + 1); preparedStatement.setString(2, "name_" + i); preparedStatement.setDate(3, date); //"積攢" SQL preparedStatement.addBatch(); //當 "積攢" 到一定程度, 就統一的執行一次. 并且清空先前 "積攢" 的 SQL if((i + 1) % 300 == 0){ preparedStatement.executeBatch(); preparedStatement.clearBatch(); } } //若總條數不是批量數值的整數倍, 則還需要再額外的執行一次. if(100000 % 300 != 0){ preparedStatement.executeBatch(); preparedStatement.clearBatch(); } long end = System.currentTimeMillis(); System.out.println("Time: " + (end - begin)); //569 JDBCTools.commit(connection); } catch (Exception e) { e.printStackTrace(); JDBCTools.rollback(connection); } finally{ JDBCTools.releaseDB(null, preparedStatement, connection); } } @Test public void testBatchWithPreparedStatement(){ Connection connection = null; PreparedStatement preparedStatement = null; String sql = null; try { connection = JDBCTools.getConnection(); JDBCTools.beginTx(connection); sql = "INSERT INTO customers VALUES(?,?,?)"; preparedStatement = connection.prepareStatement(sql); Date date = new Date(new java.util.Date().getTime()); long begin = System.currentTimeMillis(); for(int i = 0; i < 100000; i++){ preparedStatement.setInt(1, i + 1); preparedStatement.setString(2, "name_" + i); preparedStatement.setDate(3, date); preparedStatement.executeUpdate(); } long end = System.currentTimeMillis(); System.out.println("Time: " + (end - begin)); //9819 JDBCTools.commit(connection); } catch (Exception e) { e.printStackTrace(); JDBCTools.rollback(connection); } finally{ JDBCTools.releaseDB(null, preparedStatement, connection); } } /** * 向 Oracle 的 customers 數據表中插入 10 萬條記錄 * 測試如何插入, 用時最短. * 1. 使用 Statement. */ @Test public void testBatchWithStatement(){ Connection connection = null; Statement statement = null; String sql = null; try { connection = JDBCTools.getConnection(); JDBCTools.beginTx(connection); statement = connection.createStatement(); long begin = System.currentTimeMillis(); for(int i = 0; i < 100000; i++){ sql = "INSERT INTO customers VALUES(" + (i + 1) + ", 'name_" + i + "', '29-6月 -13')"; statement.addBatch(sql); } long end = System.currentTimeMillis(); System.out.println("Time: " + (end - begin)); //39567 JDBCTools.commit(connection); } catch (Exception e) { e.printStackTrace(); JDBCTools.rol
新聞熱點
疑難解答