22、jdbc入門2

guanhang89發表於2016-06-10

入門2

JdbcUtil類

public class JdbcUtil {

    // 連線引數
    // private String url = "jdbc:mysql://localhost:3306/jdbc_demo";
    private static String url = "jdbc:mysql:///jdbc_demo";
    private static String user = "root";
    private static String password = "root";

    /**
     * 返回連線物件
     */
    public static Connection getConnection() {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            return DriverManager.getConnection(url, user, password);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 關閉
     */
    public static void closeAll(Connection con, Statement stmt, ResultSet rs) {
        try {
            if (rs != null) {
                rs.close();  // 快速異常捕獲 Alt + shift + z 
                rs = null;   // 建議垃圾回收期回收資源
            }
            if (stmt != null) {
                stmt.close();
                stmt = null;
            }
            if (con != null && !con.isClosed()) {
                con.close();
                con = null;
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

批處理

很多時候,需要批量執行sql語句!

|-- Statement
    批處理相關方法
    void addBatch(String sql)     新增批處理
    void clearBatch()            清空批處理
    int[] executeBatch()         執行批處理
//javabean示例
public class Admin {

    private String userName;
    private String pwd;
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPwd() {
        return pwd;
    }
    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

}
//操作類
public class App {
    // 測試批處理操作
    @Test
    public void testBatch() throws Exception {

        // 模擬資料
        List<Admin> list = new ArrayList<Admin>();
        for (int i=1; i<21; i++) {
            Admin admin = new Admin();
            admin.setUserName("Jack" + i);
            admin.setPwd("888" + i);
            list.add(admin);
        }

        // 儲存
        AdminDao dao = new AdminDao();
        dao.save(list);
    }
}
// 封裝所有的與資料庫的操作
public class AdminDao {

    // 全域性引數
    private Connection con;
    private PreparedStatement pstmt;
    private ResultSet rs;

    // 批量儲存管理員
    public void save(List<Admin> list) {
        // SQL
        String sql = "INSERT INTO admin(userName,pwd) values(?,?)";

        try {

            // 獲取連線
            con = JdbcUtil.getConnection();
            // 建立stmt 
            pstmt = con.prepareStatement(sql);          // 【預編譯SQL語句】

            for (int i=0; i<list.size(); i++) {
                Admin admin = list.get(i);
                // 設定引數
                pstmt.setString(1, admin.getUserName());
                pstmt.setString(2, admin.getPwd());

                // 新增批處理
                pstmt.addBatch();                       // 【不需要傳入SQL】

                // 測試:每5條執行一次批處理
                if (i % 5 == 0) {
                    // 批量執行 
                    pstmt.executeBatch();
                    // 清空批處理
                    pstmt.clearBatch();
                }

            }

            // 批量執行 
            pstmt.executeBatch();
            // 清空批處理
            pstmt.clearBatch();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JdbcUtil.closeAll(con, pstmt, rs);
        }
    }
}

獲取自增長

相關表

--部門表
CREATE TABLE dept(
   deptId INT PRIMARY KEY AUTO_INCREMENT,
   deptName VARCHAR(20)
);
-- 員工
CREATE TABLE employee(
   empId INT PRIMARY KEY AUTO_INCREMENT,
   empName VARCHAR(20),
   dept_id  INT   --  外來鍵欄位   
);
-- 給員工表新增外來鍵約束
ALTER TABLE employee ADD CONSTRAINT FK_employee_dept_deptId
    FOREIGN KEY(dept_id) REFERENCES dept(deptId) ;
public class EmpDao {

    private Connection con;
    private PreparedStatement pstmt;
    private ResultSet rs;

    // 儲存員工,同時儲存關聯的部門
    public void save(Employee emp){

        // 儲存部門
        String sql_dept = "insert into dept(deptName) values(?)";
        // 儲存員工
        String sql_emp = "INSERT INTO employee (empName,dept_id) VALUES (?,?)";
        // 部門id
        int deptId = 0;

        try {
            // 連線
            con = JdbcUtil.getConnection();

            /*****儲存部門,獲取自增長*******/
            // 【一、需要指定返回自增長標記】
            pstmt = con.prepareStatement(sql_dept,Statement.RETURN_GENERATED_KEYS);
            // 設定引數
            pstmt.setString(1, emp.getDept().getDeptName());
            // 執行
            pstmt.executeUpdate();

            // 【二、獲取上面儲存的部門子增長的主鍵】
            rs =  pstmt.getGeneratedKeys();
            // 得到返回的自增長欄位
            if (rs.next()) {
                deptId = rs.getInt(1);
            }

            /*****儲存員工*********/
            pstmt = con.prepareStatement(sql_emp);
            // 設定引數
            pstmt.setString(1, emp.getEmpName());
            pstmt.setInt(2, deptId);
            pstmt.executeUpdate();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JdbcUtil.closeAll(con, pstmt, rs);
        }
    }
}

事物

事務使指一組最小邏輯操作單元,裡面有多個操作組成。 組成事務的每一部分必須要同時提交成功,如果有一個操作失敗,整個操作就回滾。

事務ACID特性

  • 原子性(Atomicity)
    原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。
  • 一致性(Consistency)
    事務必須使資料庫從一個一致性狀態變換到另外一個一致性狀態。
  • 隔離性(Isolation)
    事務的隔離性是多個使用者併發訪問資料庫時,資料庫為每一個使用者開啟的事務,不能被其他事務的運算元據所干擾,多個併發事務之間要相互隔離。
  • 永續性(Durability)
    永續性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來即使資料庫發生故障也不應該對其有任何影響

事務的特性:

原子性,是一個最小邏輯操作單元 !
一致性,事務過程中,資料處於一致狀態。
永續性, 事務一旦提交成功,對資料的更改會反映到資料庫中。
隔離性, 事務與事務之間是隔離的。

案例:
sql:

-- 賬戶表
CREATE TABLE account(
   id INT PRIMARY KEY AUTO_INCREMENT,
   accountName VARCHAR(20),
   money DOUBLE
);
-- 轉賬
UPDATE account SET money=money-1000 WHERE accountName='張三';
UPDATE account SET money=money+1000 WHERE accountName='李四';

操作類:

public class AccountDao {

    // 全域性引數
    private Connection con;
    private PreparedStatement pstmt;

    // 1. 轉賬,沒有使用事務
    public void trans1() {
        String sql_zs = "UPDATE account SET money=money-1000 WHERE accountName='張三';";
        String sql_ls = "UPDATE account SET money=money+1000 WHERE accountName='李四';";
        try {
            con = JdbcUtil.getConnection(); // 預設開啟的隱士事務
            con.setAutoCommit(true);

            /*** 第一次執行SQL ***/
            pstmt = con.prepareStatement(sql_zs);
            pstmt.executeUpdate();

            /*** 第二次執行SQL ***/
            pstmt = con.prepareStatement(sql_ls);
            pstmt.executeUpdate();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JdbcUtil.closeAll(con, pstmt, null);
        }

    }

    // 2. 轉賬,使用事務
    public void trans2() {

        String sql_zs = "UPDATE account SET money=money-1000 WHERE accountName='張三';";
        String sql_ls = "UPDATE1 account SET money=money+1000 WHERE accountName='李四';";

        try {
            con = JdbcUtil.getConnection(); // 預設開啟的隱士事務
            // 一、設定事務為手動提交
            con.setAutoCommit(false);

            /*** 第一次執行SQL ***/
            pstmt = con.prepareStatement(sql_zs);
            pstmt.executeUpdate();

            /*** 第二次執行SQL ***/
            pstmt = con.prepareStatement(sql_ls);
            pstmt.executeUpdate();

        } catch (Exception e) {
            try {
                // 二、 出現異常,需要回滾事務
                con.rollback();
            } catch (SQLException e1) {
            }
            e.printStackTrace();
        } finally {
            try {
                // 三、所有的操作執行成功, 提交事務
                con.commit();
                JdbcUtil.closeAll(con, pstmt, null);
            } catch (SQLException e) {
            }
        }

    }

    // 3. 轉賬,使用事務, 回滾到指定的程式碼段
    public void trans() {
        // 定義個標記
        Savepoint sp = null;

        // 第一次轉賬
        String sql_zs1 = "UPDATE account SET money=money-1000 WHERE accountName='張三';";
        String sql_ls1 = "UPDATE account SET money=money+1000 WHERE accountName='李四';";

        // 第二次轉賬
        String sql_zs2 = "UPDATE account SET money=money-500 WHERE accountName='張三';";
        String sql_ls2 = "UPDATE1 account SET money=money+500 WHERE accountName='李四';";

        try {
            con = JdbcUtil.getConnection(); // 預設開啟的隱士事務
            con.setAutoCommit(false);       // 設定事務手動提交

            /*** 第一次轉賬 ***/
            pstmt = con.prepareStatement(sql_zs1);
            pstmt.executeUpdate();
            pstmt = con.prepareStatement(sql_ls1);
            pstmt.executeUpdate();

            // 回滾到這個位置?
            sp = con.setSavepoint(); 


            /*** 第二次轉賬 ***/
            pstmt = con.prepareStatement(sql_zs2);
            pstmt.executeUpdate();
            pstmt = con.prepareStatement(sql_ls2);
            pstmt.executeUpdate();


        } catch (Exception e) {
            try {
                // 回滾 (回滾到指定的程式碼段)
                con.rollback(sp);
            } catch (SQLException e1) {
            }
            e.printStackTrace();
        } finally {
            try {
                // 提交
                con.commit();
            } catch (SQLException e) {
            }
            JdbcUtil.closeAll(con, pstmt, null);
        }

    }
}

相關文章