java攻城獅之路--複習JDBC(利用BeanUtils、JDBC元數據編寫通用的查詢方法;元數據;Blob;事務;批量處理)

一、利用BeanUtils的前提得要加入如下兩個jar包:java

commons-beanutils-1.8.0.jarmysql

commons-logging-1.1.1.jarsql

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.Driver
jdbcUrl=jdbc:mysql://localhost:3306/test
user=root
password=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()給對象賦值而後返回該對象

 

二、獲取數據庫中的一些元數據:shell

    @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();獲取

 

三、獲取插入記錄的主鍵值,在加入購物車時用到:數據庫

    @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);
        }
    }
獲取最新插入記錄的主鍵值

 

四、讀取 blob 數據:
 1. 使用 getBlob 方法讀取到 Blob 對象
 2. 調用 Blob 的 getBinaryStream() 方法獲得輸入流。再使用 IO 操做便可.apache

@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數據(如圖片)

 

五、事務:併發

•  事務:指構成單個邏輯工做單元的操做集合
•  事務處理:保證全部事務都做爲一個工做單元來執行,即便出現了故障,都不能改變這種執行方式。當在一個事務中執行多個操做時,要麼全部的事務都被提交(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 再次讀取同一個表, 就會多出幾行.
•  數據庫事務的隔離性: 數據庫系統必須具備隔離併發運行各個事務的能力, 使它們不會相互影響,
    避免各類併發問題.
•  一個事務與其餘事務隔離的程度稱爲隔離級別. 數據庫規定了多種事務隔離級別, 不一樣隔離級別對應不一樣的
   干擾程度,隔離級別越高, 數據一致性就越好, 但併發性越弱.
•  Oracle 支持的 2 種事務隔離級別: READ COMMITED, SERIALIZABLE,Oracle 默認的事務隔離級別爲:
    READ COMMITED。
•  Mysql 支持 4 中事務隔離級別. Mysql 默認的事務隔離級別爲: REPEATABLE READ
在 MySql 中設置隔離級別:
•  每啓動一個 mysql 程序, 就會得到一個單獨的數據庫鏈接. 每一個數據庫鏈接都有一個全局變量
   @@tx_isolation, 表示當前的事務隔離級別. MySQL 默認的隔離級別爲 Repeatable Read
•  查看當前的隔離級別: SELECT @@tx_isolation;
•  設置當前 mySQL 鏈接的隔離級別: 
    – set  transaction isolation level read committed;
•  設置數據庫系統的全局的隔離級別:
    – set global transaction isolation level read committed;

關於事務:
1. 若是多個操做, 每一個操做使用的是本身的單獨的鏈接, 則沒法保證事務.
2. 具體步驟: 1). 事務操做開始前, 開始事務:取消Connection 的默認提交行爲. connection.setAutoCommit(false).
2). 若是事務的操做都成功,則提交事務: connection.commit();
3). 回滾事務: 若出現異常, 則在 catch 塊中回滾事務:connection.rollback();ide

    @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 來設置事務的隔離級別

 

六、批量處理JDBC語句提升處理速度:函數

•  當須要成批插入或者更新記錄時。能夠採用Java的批量更新機制,
   這一機制容許多條語句一次性提交給數據庫批量處理。一般狀況下比單獨提交處理更有效率
•  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.rollback(connection);
        } finally{
            JDBCTools.releaseDB(null, statement, connection);
        }
    }
批量處理測試例子
相關文章
相關標籤/搜索