day03

JDBC

結(jié)果集元數(shù)據(jù)

ResultSetMetaData用于描述查詢結(jié)果的相關(guān)信息,其中包含列名稱,列數(shù)量,類數(shù)據(jù)類型等.

原理:

1.png

使用案例:

public static void main(String[] args) {
    Connection conn = null;
    try {
        conn = DBUtils.getConnection();
        String sql = "select * from robin_user";
        Statement st = conn.createStatement();
        ResultSet rs = st.executeQuery(sql);
        
        //結(jié)果集元數(shù)據(jù)
        ResultSetMetaData meta = rs.getMetaData();
        int n = meta.getColumnCount();
        
        for (int i = 1; i <=n ; i++) {
            // i = 1 ... n
            String name = meta.getColumnName(i);
            System.out.println(name);
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        DBUtils.close(conn);
    }
}

作業(yè):

/**
 * 打印一個(gè)SQL查詢結(jié)果的全部列名
 * @param sql
 */
public static void print(String sql) {
    //...
}

JDBC 實(shí)務(wù)控制

數(shù)據(jù)庫(kù)提供了實(shí)務(wù)控制功能,支持ACID特性.

JDBC提供了API,方便的調(diào)用數(shù)據(jù)庫(kù)的實(shí)務(wù)功能,其方法有:

相關(guān)API:

  • Connection.getAutoCommit():獲得當(dāng)前事務(wù)的提交方式,默認(rèn)為true
  • Connection.setAutoCommit():設(shè)置事務(wù)的的提交屬性,參數(shù)是
    • true:自動(dòng)提交;
    • false:不自動(dòng)提交;
  • Connection.commit():提交事務(wù)
  • Connection.rollback():回滾事務(wù)

API調(diào)用模板:

Connection conn = null;
try {
    conn = DBUtils.getConnection();
    //取消自動(dòng)提交,后續(xù)手動(dòng)提交
    conn.setAutoCommit(false);
    //SQL... update
    //SQL... update
    // 余額不足 拋出異常 throw e;
    //SQL... update
    conn.commit();
} catch (Exception e) {
    e.printStackTrace();
    DBUtils.rollback(conn);
} finally {
    DBUtils.close(conn);
}

提示:事務(wù)API經(jīng)典的用法是采用如下模板,其中DBUtils.rollback()方法封裝了回滾方法,其聲明如下:

public static void close(Connection conn) {
    if(conn!=null) {
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

事務(wù)測(cè)試案例數(shù)據(jù):

create table account(
    id int(6),
    name varchar(100),
    balance float(8,2)
);

insert into account (id,name,balance) values (1,'范老師',500);

insert into account (id,name,balance) values (2,'劉老師',1500); 

insert into account (id,name,balance) values (3,'河仙姑',2000);

update account set balance=balance-1000 where id=2;
update account set balance=balance+1000 where id=1;

commit;

rollback;

案例:

public class Demo03 {
    public static void main(String[] args) {
        pay(3,4,200);
        System.out.println("ok");
    }

    public static void pay(int from,int to,double money) {
        String sql1 = "update account set balance=balance+? where id=?";
        String sql2 = "select balance from account where id=?";
        Connection conn = null;
        try {
            conn = DBUtils.getConnection();
            conn.setAutoCommit(false);
            PreparedStatement ps = conn.prepareStatement(sql1);

            //減錢
            ps.setDouble(1, -money);
            ps.setInt(2, from);
            int n = ps.executeUpdate();
            if(n!=1) {
                throw new Exception("扣錯(cuò)了");
            }

            //增加
            ps.setDouble(1, money);
            ps.setInt(2, to);
            n = ps.executeUpdate();
            if(n!=1) {
                throw new Exception("加錯(cuò)了");
            }
            ps.close();

            //檢查
            ps = conn.prepareStatement(sql2);
            ps.setInt(1, from);
            ResultSet rs = ps.executeQuery();
            while(rs.next()) {
                double bal = rs.getDouble(1);
                if(bal<0) {
                    throw new Exception("透支");
                }
            }
            conn.commit();
        } catch (Exception e) {
            e.printStackTrace();
            DBUtils.rollback(conn);
        } finally {
            DBUtils.close(conn);
        }
    }
}

批量更新

批量更新的優(yōu)勢(shì)

  • 批處理:發(fā)送到數(shù)據(jù)庫(kù)作為一個(gè)單元執(zhí)行的一組更新語(yǔ)句
  • 批處理降低了應(yīng)用程序與數(shù)據(jù)庫(kù)之間的網(wǎng)絡(luò)調(diào)用
  • 相比單個(gè)SQL語(yǔ)句的處理,批處理更為有效
2.png

用法:

  • addBatch(String sql)

    • Statement類的方法,可以將多條sql語(yǔ)句添加Statement對(duì)象的SQL語(yǔ)句列表中
  • addBatch()

    • PreparedStatement類的方法,可以將多條預(yù)編譯的sql語(yǔ)句添加到PreparedStatement對(duì)象的SQL語(yǔ)句列表中
  • executeBatch()

    • 把Statemennt對(duì)象或PreparedStatemenn對(duì)象語(yǔ)句列表中的所有SQL語(yǔ)句發(fā)送給數(shù)據(jù)庫(kù)進(jìn)行處理
  • clearBatch()

    • 清空當(dāng)前SQL語(yǔ)句列表

批量執(zhí)行DDL

public class Demo04 {
    public static void main(String[] args) {
        String sql1 = "create table log_01(id int(8),msg varchar(100))";
        String sql2 = "create table log_02(id int(8),msg varchar(100))";
        String sql3 = "create table log_03(id int(8),msg varchar(100))";

        // 執(zhí)行一批SQL
        Connection conn = null;
        try {
            conn = DBUtils.getConnection();
            Statement st = conn.createStatement();

            // sql1 添加到Statement的緩存中
            st.addBatch(sql1);
            st.addBatch(sql2);
            st.addBatch(sql3);

            // 執(zhí)行一批SQL
            int[] ary = st.executeBatch();
            System.out.println(Arrays.toString(ary));
            System.out.println("OK");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DBUtils.close(conn);
        }
    }
}

批量插入數(shù)據(jù)

public class Demo05 {
    public static void main(String[] args) {
        String sql = "insert into robin_user (id,name,pwd) values (?,?,?)";
        Connection conn = null;
        try {
            conn = DBUtils.getConnection();
            PreparedStatement ps = conn.prepareStatement(sql);
            for (int i = 0; i < 100; i++) {
                //替換參數(shù)
                ps.setInt(1, i);
                ps.setString(2, "name"+i);
                ps.setString(3, "123");
                //將參數(shù)添加到ps緩沖區(qū)
                ps.addBatch();
            }
            //批量執(zhí)行
            int[] ary = ps.executeBatch();
            System.out.println(Arrays.toString(ary));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DBUtils.close(conn);
        }
    }
}

防止OutOfMemory

  • 如果Preparedstatement對(duì)象中的緩存列表包含過(guò)多的待處理數(shù)據(jù),可能會(huì)產(chǎn)生OutOfMerry錯(cuò)誤

返回自動(dòng)主鍵

JDBC API 提供了返回插入數(shù)據(jù)期間生成的ID的API,

API方法:

  1. PrepareStatement ps = con.prepareStatement(sql,列名列表);
  2. rs = stmt.getGeneratement();
3.png

create table r_post(
id int(8) auto_increment primary key ,
content varchar(100),
k_id int(8)
);

create table r_keywords(
id int(8) auto_increment primary key,
word varchar(8)
);

需要執(zhí)行的SQL:

insert into r_keywords (id,word) values (null,?);
insert into r_post (id,content,k_id) values (null,?,?)

案例:

public class Demo06 {
    public static void main(String[] args) {
        Connection conn = null;
        try {
            conn = DBUtils.getConnection();
            conn.setAutoCommit(false);
            String sql = "insert into r_keywords (id,word) values (null,?)";
            String[] cols = {"id"};
            //自動(dòng)生成序號(hào)的列名
            PreparedStatement ps = conn.prepareStatement(sql,cols);
            ps.setString(1, "霧霾");
            int n = ps.executeUpdate();
            if(n!=1) {
                throw new Exception("話題添加失敗");
            }
            //獲取自動(dòng)生成的ID
            ResultSet rs = ps.getGeneratedKeys();
            int id = -1;
            while(rs.next()) {
                id = rs.getInt(1);
            }
            rs.close();
            ps.close();

            sql = "insert into r_post (id,content,k_id) values (null,?,?)";
            ps=conn.prepareStatement(sql);
            ps.setString(1, "今天天氣不錯(cuò),晚上有霧霾");
            ps.setInt(2, id);
            n = ps.executeUpdate();
            if(n!=1) {
                throw new Exception("天氣太糟");
            }
            conn.commit();
            System.out.println("OK");
        } catch (Exception e) {
            e.printStackTrace();
            DBUtils.rollback(conn);
        } finally {
            DBUtils.close(conn);
        }
    }
}

作業(yè)

  1. 設(shè)計(jì)一個(gè)方法打印一個(gè)SQL查詢結(jié)果的全部列名
  2. 利用JDBC事物保護(hù)一個(gè)匯款業(yè)務(wù)的完整性
  3. 批量建立10個(gè)表,再批量的向每個(gè)插入100條數(shù)據(jù)
  4. 向部門表插入一個(gè)數(shù)據(jù)并且返回自動(dòng)生成的ID
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 非本人總結(jié)的筆記,抄點(diǎn)筆記復(fù)習(xí)復(fù)習(xí)。感謝傳智博客及黑馬程序猿記筆記啊記筆記 Hibernate的查詢操作 Hibe...
    鍵盤瞎閱讀 502評(píng)論 0 1
  • 經(jīng)驗(yàn):1.sqlite表中的類型限定并不起作用,底層所有的數(shù)據(jù)都是String,為了節(jié)約手機(jī)內(nèi)存 2.4.0版本以...
    123yuan123閱讀 415評(píng)論 0 1
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 34,706評(píng)論 18 399
  • JDBC概述 在Java中,數(shù)據(jù)庫(kù)存取技術(shù)可分為如下幾類:JDBC直接訪問(wèn)數(shù)據(jù)庫(kù)、JDO技術(shù)、第三方O/R工具,如...
    usopp閱讀 3,640評(píng)論 3 75
  • 能夠波瀾不驚地看著以前那個(gè)非常非常喜歡的人,大抵都經(jīng)歷過(guò)徹底的失望。 橙子以前是一個(gè)很愛(ài)撒嬌的女孩...
    懷綺閱讀 324評(píng)論 0 0

友情鏈接更多精彩內(nèi)容