01.JDBC概念梳理

SQL語句執行流程

JDBC執行數據庫操作語句,首先需要將sql語句打包成爲網絡字節流,傳遞給數據庫,數據庫經過解包,然後編譯sql語句,最後執行,然後將結果通過字節流的形式返回給JDBC API

簡單的來說大致分爲以下幾點:

  • JDBC打包sql語句

  • 發送字節流至數據庫

  • 數據庫解包

  • 檢查sql語法,編譯sql

  • 執行sql語句

  • 將sql語句返回給JDBC 接口
    <br/>

    數據庫的鏈接步驟

    <br/>

  • 註冊驅動 (Driver)

  • 建立連接(創建Connection)

  • 創建執行sql語句(通常是創建Statement或者其子類)

  • 執行語句

  • 處理執行結果(在非查詢語句中,該步驟是可以省略的)

  • 釋放相關資源

案例

    @Test
    public void wholeExample(){
        try {
            //1.註冊驅動
            Class.forName("com.mysql.jdbc.Driver");
            //2.獲取數據庫連接
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root","123456");
            //3.創建執行句柄
            Statement stmt = conn.createStatement();
            //4.執行sql語句
            ResultSet rs = stmt.executeQuery("select * from user");
            //5.處理執行結果
            while(rs.next()){
                System.out.println("id:"+rs.getInt(1)+"\tname:"+rs.getString(2)+"\tbirthday:"+rs.getDate(3)+"\tmoney:"+rs.getFloat(4));
            }
            //6.釋放資源
            rs.close();
            stmt.close();
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

數據類型

<br/>

CLOB

當我們存放大量的文本信息時,數據庫中的varchar或者varchar2肯定是不能滿足的,varchar2好像最多只能有4000個長度,存放一篇很長的文章或者一個文本信息,我們採用CLOB類型

BLOB

針對二進制文件進行的存取,比如圖片,音頻等信息

//stream文件流
PreparedStatement.setBlob(index, stream)

SQL數據類型與Java數據類型

<br/>

01.JDBC概念梳理

事務

數據庫的事務是保證數據完整性的一種機制,簡而言之,就是怎樣確保數據的執行過程要麼都成功,要麼都失敗

ACID機制

<br/>

  • 原子性(atomicity):組成事務處理的語句形成了一個邏輯單元,不能只執行其中的一部分

  • 一致性(consistency):在事務處理執行前後,數據庫是一致的(兩個賬戶要麼都變,或者都不變)

  • 隔離性(isolcation):一個事務處理對另一個事務處理沒有影響

  • 持續性(durability):事務處理的效果能夠被永久保存下來

Jdbc的事務默認是打開的,也就是說執行每一步操作的話,事務都會隱式的進行提交,在拋出異常之前,我們的更改操作已經同步到了數據庫中去

事務控制函數

//提交事務

  • connection.commit();

//回滾事務

  • connection.rollback();

分佈式事務

通常所說的跨庫事務,要求幾個數據庫的事務在一個應用中保持一致,JTA就是爲了解決這個問題而誕生的

PreparedStatement接口

在數據庫操作中PreparedStatement會帶來很大的方便,減少拼寫sql字符串帶來的麻煩,防止SQL注入的發生.

  • PreparedStatement是Statement的子類

  • PreparedStatement是一個預處理命令的Statement實現

CallableStatement接口

在數據庫操作中調用數據庫中的存儲過程

案例:執行有參數有返回值的存儲過程

  • 創建一個存儲過程
create or replace procedure test1(in id integer,in name varchar(20),in money float,out counter integer)
as
begin
    insert into user values(id,name,now(),money);
    select count(1) into counter from user;
    commit;
end test1;
  • 編寫測試代碼,在需要將值返回時,需要對其進行註冊
    @Test
    public void callProcedureWithParamWithResult() throws SQLException{
        Connection conn = null;
        CallableStatement stmt = null;
        ResultSet rs = null;
        try {
            conn = ConnCreate.getConnection("jdbc:mysql://localhost:3306/test",
                    "root", "123456");
            String sql = "{call test1(?,?,?,?)}";
            stmt = conn.prepareCall(sql);
            stmt.setInt(1, 17);
            stmt.setString(2, "test");
            stmt.setFloat(3, 6000);
            stmt.registerOutParameter(1, Types.INTEGER);
            stmt.executeUpdate();
            int counter = stmt.getInt(4);
            System.out.println(counter);
        } finally {
            ConnCreate.close(conn, stmt, rs);
        }
    }

批處理

<br/>
//添加一條條的sql

  • stmt.addBatch(sql)

// 執行批處理

  • stmt.executeBatch()
    <br/>

    分頁技術

利用sql語句進行分頁(eg: mysql的limit ? ?, 一個offsize偏移量,另一個pagesize頁面數量)

 @Test
    public void page() throws SQLException{
        page(100,20);
    }

    static void page(int start,int total) throws SQLException{
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            conn = ConnCreate.getConnection("jdbc:mysql://localhost:3306/test",
                    "root", "123456");
            String sql = "select * from user limit ?,?";
            stmt = conn.prepareStatement(sql);
            stmt.setInt(1, start);
            stmt.setInt(2, total);
            rs = stmt.executeQuery();
            while(rs.next()) //向下滾動
            {
                System.out.println("name:"+rs.getString(2)+"id:"+rs.getInt(1));
            }
        } finally {
            ConnCreate.close(conn, stmt, null);
        }
    }

連接池

使用jdbc最大的開銷之一就是創建數據庫,當我們頻繁的創建數據庫時,勢必影響應用的效率,或者在數據庫關閉出現問題時,我們不能馬上釋放,時間長一些,整個數據庫的 資源將會被我們的應用耗盡

  • C3P0

  • DBCP

ResultSetMetaData

如果我們不知道我們的一個sql語句查詢了幾列結果集,並且每列的列名,類型等信息,這個時候我們應該使用ResultSetMetaData

01.JDBC概念梳理

<br/>

案例

 @Test
    public void resultMeta() throws SQLException{
        String sql="select * from user";
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            conn = ConnFactory.getConnection();
            stmt = conn.prepareStatement(sql);
            rs = stmt.executeQuery();
            ResultSetMetaData rsmd = rs.getMetaData();
            int count = rsmd.getColumnCount();
            for(int i=1;i<=count;++i){
                System.out.println("Type:"+rsmd.getColumnType(i));
                System.out.println("ColumnName:"+rsmd.getColumnName(i));
                System.out.println("ColumnLable:"+rsmd.getColumnLabel(i));
            }
        } finally{
            ConnFactory.close(conn, stmt, rs);
        }

    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章