溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

01.JDBC概念梳理

發(fā)布時間:2020-08-05 17:40:04 來源:網(wǎng)絡 閱讀:399 作者:IMUKL8 欄目:軟件技術(shù)

SQL語句執(zhí)行流程

JDBC執(zhí)行數(shù)據(jù)庫操作語句,首先需要將sql語句打包成為網(wǎng)絡字節(jié)流,傳遞給數(shù)據(jù)庫,數(shù)據(jù)庫經(jīng)過解包,然后編譯sql語句,最后執(zhí)行,然后將結(jié)果通過字節(jié)流的形式返回給JDBC API

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

  • JDBC打包sql語句

  • 發(fā)送字節(jié)流至數(shù)據(jù)庫

  • 數(shù)據(jù)庫解包

  • 檢查sql語法,編譯sql

  • 執(zhí)行sql語句

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

    數(shù)據(jù)庫的鏈接步驟

    <br/>

  • 注冊驅(qū)動 (Driver)

  • 建立連接(創(chuàng)建Connection)

  • 創(chuàng)建執(zhí)行sql語句(通常是創(chuàng)建Statement或者其子類)

  • 執(zhí)行語句

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

  • 釋放相關(guān)資源

案例

    @Test
    public void wholeExample(){
        try {
            //1.注冊驅(qū)動
            Class.forName("com.mysql.jdbc.Driver");
            //2.獲取數(shù)據(jù)庫連接
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root","123456");
            //3.創(chuàng)建執(zhí)行句柄
            Statement stmt = conn.createStatement();
            //4.執(zhí)行sql語句
            ResultSet rs = stmt.executeQuery("select * from user");
            //5.處理執(zhí)行結(jié)果
            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();
        }
    }

數(shù)據(jù)類型

<br/>

CLOB

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

BLOB

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

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

SQL數(shù)據(jù)類型與Java數(shù)據(jù)類型

<br/>

01.JDBC概念梳理

事務

數(shù)據(jù)庫的事務是保證數(shù)據(jù)完整性的一種機制,簡而言之,就是怎樣確保數(shù)據(jù)的執(zhí)行過程要么都成功,要么都失敗

ACID機制

<br/>

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

  • 一致性(consistency):在事務處理執(zhí)行前后,數(shù)據(jù)庫是一致的(兩個賬戶要么都變,或者都不變)

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

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

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

事務控制函數(shù)

//提交事務

  • connection.commit();

//回滾事務

  • connection.rollback();

分布式事務

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

PreparedStatement接口

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

  • PreparedStatement是Statement的子類

  • PreparedStatement是一個預處理命令的Statement實現(xiàn)

CallableStatement接口

在數(shù)據(jù)庫操作中調(diào)用數(shù)據(jù)庫中的存儲過程

案例:執(zhí)行有參數(shù)有返回值的存儲過程

  • 創(chuàng)建一個存儲過程
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)

// 執(zhí)行批處理

  • stmt.executeBatch()
    <br/>

    分頁技術(shù)

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

 @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最大的開銷之一就是創(chuàng)建數(shù)據(jù)庫,當我們頻繁的創(chuàng)建數(shù)據(jù)庫時,勢必影響應用的效率,或者在數(shù)據(jù)庫關(guān)閉出現(xiàn)問題時,我們不能馬上釋放,時間長一些,整個數(shù)據(jù)庫的 資源將會被我們的應用耗盡

  • C3P0

  • DBCP

ResultSetMetaData

如果我們不知道我們的一個sql語句查詢了幾列結(jié)果集,并且每列的列名,類型等信息,這個時候我們應該使用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);
        }

    }
向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI