day03

JDBC

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

ResultSetMetaData用于描述查詢(xún)結(jié)果的相關(guān)信息,其中包含列名稱(chēng)榆纽,列數(shù)量夺英,類(lèi)數(shù)據(jù)類(lèi)型等.

原理:

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查詢(xún)結(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);

            //減錢(qián)
            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類(lèi)的方法蛙卤,可以將多條sql語(yǔ)句添加Statement對(duì)象的SQL語(yǔ)句列表中
  • addBatch()

    • PreparedStatement類(lèi)的方法,可以將多條預(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查詢(xún)結(jié)果的全部列名
  2. 利用JDBC事物保護(hù)一個(gè)匯款業(yè)務(wù)的完整性
  3. 批量建立10個(gè)表,再批量的向每個(gè)插入100條數(shù)據(jù)
  4. 向部門(mén)表插入一個(gè)數(shù)據(jù)并且返回自動(dòng)生成的ID
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末已维,一起剝皮案震驚了整個(gè)濱河市行嗤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌垛耳,老刑警劉巖栅屏,帶你破解...
    沈念sama閱讀 211,423評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異堂鲜,居然都是意外死亡栈雳,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,147評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)缔莲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)哥纫,“玉大人,你說(shuō)我怎么就攤上這事痴奏≈В” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,019評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵读拆,是天一觀的道長(zhǎng)擅憔。 經(jīng)常有香客問(wèn)我,道長(zhǎng)建椰,這世上最難降的妖魔是什么雕欺? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,443評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮棉姐,結(jié)果婚禮上屠列,老公的妹妹穿的比我還像新娘。我一直安慰自己伞矩,他們只是感情好笛洛,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,535評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著乃坤,像睡著了一般苛让。 火紅的嫁衣襯著肌膚如雪沟蔑。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,798評(píng)論 1 290
  • 那天狱杰,我揣著相機(jī)與錄音瘦材,去河邊找鬼。 笑死仿畸,一個(gè)胖子當(dāng)著我的面吹牛食棕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播错沽,決...
    沈念sama閱讀 38,941評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼簿晓,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了千埃?” 一聲冷哼從身側(cè)響起憔儿,我...
    開(kāi)封第一講書(shū)人閱讀 37,704評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎放可,沒(méi)想到半個(gè)月后谒臼,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,152評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吴侦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,494評(píng)論 2 327
  • 正文 我和宋清朗相戀三年屋休,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片备韧。...
    茶點(diǎn)故事閱讀 38,629評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡劫樟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出织堂,到底是詐尸還是另有隱情叠艳,我是刑警寧澤,帶...
    沈念sama閱讀 34,295評(píng)論 4 329
  • 正文 年R本政府宣布易阳,位于F島的核電站附较,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏潦俺。R本人自食惡果不足惜拒课,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,901評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望事示。 院中可真熱鬧早像,春花似錦、人聲如沸肖爵。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)劝堪。三九已至冀自,卻和暖如春揉稚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背熬粗。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,978評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工搀玖, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人荐糜。 一個(gè)月前我還...
    沈念sama閱讀 46,333評(píng)論 2 360
  • 正文 我出身青樓巷怜,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親暴氏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,499評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

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