數(shù)據(jù)庫(kù)(三)2018-08-26

1. JDBC的簡(jiǎn)介
概述: 就是Java用來(lái)操作不同數(shù)據(jù)庫(kù)(DBMS)的類庫(kù)(技術(shù)), 本質(zhì)就是一些類和接口.
    /*
        類: DriverManager
        
        接口: Driver, Connection, Statement, PreparedStatement, ResultSet
    */
    
    //Java Data Base  Connectivity, Java數(shù)據(jù)庫(kù)連接(技術(shù)).
    
    /*
        集合: 就是Java用來(lái)存儲(chǔ)不同類型數(shù)據(jù)的容器, 本質(zhì)就是一些類和接口.
            接口: Collection, Set, List, Map
            類: ArrayList, HashSet, HashMap
            
            面試題: 請(qǐng)求寫代碼實(shí)現(xiàn), 模擬棧的數(shù)據(jù)結(jié)構(gòu)(先進(jìn)后出)特點(diǎn)?
        
        
        IO流: 就是Java用來(lái)傳輸數(shù)據(jù)的技術(shù), 本質(zhì)就是一些類和接口.
            抽象類:    InputStream, OutputStream, Reader, Writer
            
            實(shí)現(xiàn)類: FileInputStream, BufferedInputStream, FileReader, BufferedReader
            
        總結(jié): 集合的頂層都是接口, IO流的頂層都是抽象類.
    
    */

核心功能:
    A: 連接數(shù)據(jù)庫(kù).
    B: 向數(shù)據(jù)庫(kù)發(fā)送SQL語(yǔ)句.
    C: 操作數(shù)據(jù)庫(kù)返回的 結(jié)果集.
        如果操作的是更新語(yǔ)句(增刪改),  返回的結(jié)果集是: int 類型
        如果操作的是查詢語(yǔ)句,  返回的結(jié)果集是: ResultSet 類型
  1. 什么是驅(qū)動(dòng)?
    就是設(shè)備間進(jìn)行通信的橋梁.
  1. JDBC的原理是什么:
    我們知道JDBC是用來(lái)操作不同數(shù)據(jù)庫(kù)的, 但是操作不同的數(shù)據(jù)庫(kù)需要使用不同的驅(qū)動(dòng).
    eg: 我們想操作MySQL數(shù)據(jù)庫(kù), 就需要安裝MySQL的驅(qū)動(dòng), 我們想操作Oracle數(shù)據(jù)庫(kù), 就需要安裝Oracle數(shù)據(jù)庫(kù)的驅(qū)動(dòng), 如果我們操作SQLServer數(shù)據(jù)庫(kù),就需要安裝SQLServer數(shù)據(jù)庫(kù)的驅(qū)動(dòng), 這樣做是比較麻煩的. 因?yàn)镴ava已經(jīng)提供了大量的類和接口了, 但是要要求額外記憶一些其他的類和接口, 這樣就增加了程序員的學(xué)習(xí)難度. 后來(lái)Sun公司發(fā)現(xiàn)了這個(gè)問(wèn)題, 就和各大數(shù)據(jù)庫(kù)生產(chǎn)商協(xié)商決定, 由Sun公司提供統(tǒng)一的規(guī)范(就是一些類和接口), 數(shù)據(jù)庫(kù)生產(chǎn)商提供具體的實(shí)現(xiàn). Sun公司提供的這些類和接口就是: JDBC.

4. JDBC的代碼演示

A: 創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)web04.
B: 在數(shù)據(jù)庫(kù)web04中創(chuàng)建一個(gè)表(users);
    create table users(
        id int primary key auto_increment;
        username varchar(20),
        password varchar(20)
    );
C: 往數(shù)據(jù)表中添加數(shù)據(jù).
    insert into user values(null,'aaa','123');
    insert into user values(null,'bbb','321');
    insert into user values(null,'ccc','456');
    insert into user values(null,'ddd','654');
    
D: 通過(guò)JDBC操作表數(shù)據(jù).
    1) 導(dǎo)入驅(qū)動(dòng).
    2) 注冊(cè)驅(qū)動(dòng).
    3) 獲取連接對(duì)象.
    4) 根據(jù)連接對(duì)象, 獲取可以操作SQL語(yǔ)句的對(duì)象.
    5) 執(zhí)行SQL語(yǔ)句, 獲取結(jié)果集.
        如果操作的是更新語(yǔ)句(增刪改),  返回的結(jié)果集是: int 類型
        如果操作的是查詢語(yǔ)句,  返回的結(jié)果集是: ResultSet 類型
    6) 操作結(jié)果集.
    7) 釋放資源.
5. JDBC的API詳解之: DriverManager(類)
作用: 主要用于驅(qū)動(dòng)管理及獲取連接對(duì)象的.

作用一:    注冊(cè)驅(qū)動(dòng).
    //                              MySQL的驅(qū)動(dòng)或者Oracle的驅(qū)動(dòng)
    public static void registerDriver(Driver driver);   //注冊(cè)驅(qū)動(dòng)的意思, 形參是誰(shuí)的驅(qū)動(dòng), 就注冊(cè)誰(shuí).
    
    //Driver類就是MySQL數(shù)據(jù)庫(kù)提供的 驅(qū)動(dòng)類
    public class com.mysql.jdbc.Driver implements java.sql.Driver{
        
    }
    
    //記憶: 實(shí)際開發(fā)中, 我們不用上述的方式注冊(cè)驅(qū)動(dòng), 因?yàn)樯鲜鲎?cè)驅(qū)動(dòng)的方式會(huì)導(dǎo)致驅(qū)動(dòng)程序注冊(cè)兩次.
    //所以: 我們通過(guò)反射的方式加載 com.mysql.jdbc.Driver類的字節(jié)碼文件, 從而來(lái)自動(dòng) 注冊(cè)驅(qū)動(dòng).
    Class.forName("com.mysql.jdbc.Driver");         //驅(qū)動(dòng)類的全路徑
    

作用二: 獲取連接對(duì)象.
    public static Connection getConnection(String url, String username, String password);   //獲取連接對(duì)象.
    /*
        url: 數(shù)據(jù)庫(kù)連接字符串.
            格式:
                大白話:  連接方式:要操作的DBMS://要操作的數(shù)據(jù)庫(kù)的IP地址或者主機(jī)名:端口號(hào)/要操作的具體的數(shù)據(jù)庫(kù)
                專業(yè):    協(xié)議:子協(xié)議:要操作的DBMS://要操作的數(shù)據(jù)庫(kù)的IP地址或者主機(jī)名:端口號(hào)/要操作的具體的數(shù)據(jù)庫(kù)
                
            例如:
                jdbc:mysql://127.0.0.1:3306/web04
                jdbc:mysql://localhost:3306/web04
                
                如果操作的是本地?cái)?shù)據(jù)庫(kù)(DBMS), 上述的寫法可以優(yōu)化為:
                    jdbc:mysql:///web04
        
        
        username: 要操作的數(shù)據(jù)庫(kù)(DBMS)的賬號(hào)
        
        
        password: 要操作的數(shù)據(jù)庫(kù)(DBMS)的密碼
    
    */
6. JDBC的API詳解之: Connection(接口)
Connection: 連接對(duì)象

作用一: 獲取可以執(zhí)行SQL語(yǔ)句的對(duì)象.            //掌握
    public Statement createStatement();                     //獲取可以執(zhí)行SQL語(yǔ)句的對(duì)象.
    
    public PreparedStatement prepareStatement(String sql);  //獲取可以執(zhí)行SQL語(yǔ)句的對(duì)象, 具有預(yù)編譯功能, 可以解決SQL注入攻擊問(wèn)題.


作用二: 可以進(jìn)行事務(wù)管理.      
    public void setAutoCommit(boolean flag);                //設(shè)置是否開啟事務(wù)的自動(dòng)提交功能, 相當(dāng)于我們昨天講解的: 開啟事務(wù).
    public void commit();                                   //提交事務(wù)
    public void rollback();                                 //事務(wù)回滾
    public void setTransactionIsolation(int level);         //設(shè)置事務(wù)的隔離級(jí)別
    
    
Connection接口中的常量:
    public static final int TRANSACTION_NONE = 0;
    public static final int TRANSACTION_READ_UNCOMMITTED = 1;
    public static final int TRANSACTION_READ_COMMITTED = 2;
    public static final int TRANSACTION_REPEATABLE_READ = 4;
    public static final int TRANSACTION_SERIALIZABLE = 8;
7. JDBC的API詳解之: Statement(接口)
Statement: 可以操作SQL語(yǔ)句的對(duì)象.

作用一:    執(zhí)行SQL語(yǔ)句.                //掌握
    public ResultSet executeQuery(String sql);      //執(zhí)行查詢語(yǔ)句
    public int executeUpdate(String sql);           //執(zhí)行更新語(yǔ)句
    

作用二: 可以執(zhí)行批處理.               
    //批處理只針對(duì)更新語(yǔ)句有效.
    
    public void addBatch(String sql);   //把SQL語(yǔ)句添加到批處理(指令)中.
    public int[] executeBatch();        //執(zhí)行批處理(指令)
    public void clearBatch();           //清除批出(指令)
    
    
    users:          添加5條數(shù)據(jù)
    orders:         刪除2條數(shù)據(jù), 修改4條數(shù)據(jù)
    orderitem:      添加10條數(shù)據(jù), 改3條數(shù)據(jù)
    exam:           刪5條數(shù)據(jù)
8. JDBC的API詳解之: ResultSet(接口)
ResultSet: 執(zhí)行查詢語(yǔ)句后的結(jié)果集對(duì)象.

public boolean next();  //判斷結(jié)果集中是否還有數(shù)據(jù).     類似于Iterator#hasNext().

public XXX getXxx(int columnIndex);     //根據(jù)列的編號(hào), 獲取該列的信息, Xxx是數(shù)據(jù)類型的意思  
public XXX getXxx(String columnName);   //根據(jù)列的名字, 獲取該列的信息, Xxx是數(shù)據(jù)類型的意思,  個(gè)人建議用這種方式.
    //getInt(), getString(), getObject();
9. JDBC釋放資源的優(yōu)化代碼. //重點(diǎn)掌握.
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try {
    //2 alter + enter: 處理異常
    Class.forName("com.mysql.jdbc.Driver");
    //3
    conn = DriverManager.getConnection("jdbc:mysql:///web04", "root", "123");
    //4
    stat = conn.createStatement();
    //5
    String sql = "select * from users";
    rs = stat.executeQuery(sql);
    //6
    while (rs.next()) {
        int uid = rs.getInt("uid");
        String username = rs.getString("username");
        String password = rs.getString("password");
        System.out.println(uid + "..." + username + "..." + password);
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    //7
    try {
        if(rs != null) {
            rs.close();     //alt + ↑, 代碼的向上移動(dòng)
            rs = null;      //GC會(huì)優(yōu)先回收null對(duì)象.
           // System.out.println(1/0);
            System.out.println("rs 關(guān)了");
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        try {
            if (stat != null) {
                stat.close();
                stat = null;
                System.out.println("stat 關(guān)了");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (conn != null) {
                    conn.close();
                    conn = null;
                    System.out.println("conn 關(guān)了");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
10. JDBC對(duì)表數(shù)據(jù)的CURD操作
public class Test02_JDBC對(duì)數(shù)據(jù)的CURD操作 {
    //alter + enter: 給出建議   Junit4

    /**
     * JDBC的查
     */
    @Test
    public void method1() {
        System.out.println("JDBC的查, 自己實(shí)現(xiàn)");
    }

    /**
     * JDBC的增
     */
    @Test
    public void method2() {
        Connection conn = null;
        Statement stat = null;
        try {
            //2 alter + enter: 處理異常
            Class.forName("com.mysql.jdbc.Driver");
            //3
            conn = DriverManager.getConnection("jdbc:mysql:///web04", "root", "123");
            //4
            stat = conn.createStatement();
            //5
            String sql = "insert Into users values(null,'tianqi','pw567')";
           int num = stat.executeUpdate(sql);
            //6
            if(num > 0) {
                System.out.println("添加成功");
            } else {
                System.out.println("添加失敗");
            }
            //7
            stat.close();
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * JDBC的改
     */
    @Test
    public void method3() {
        Connection conn = null;
        Statement stat = null;
        try {
            //2 alter + enter: 處理異常
            Class.forName("com.mysql.jdbc.Driver");
            //3
            conn = DriverManager.getConnection("jdbc:mysql:///web04", "root", "123");
            //4
            stat = conn.createStatement();
            //5
            String sql = "update users set password='777' where uid = 6;";
            int num = stat.executeUpdate(sql);
            //6
            if(num > 0) {
                System.out.println("修改成功");
            } else {
                System.out.println("修改失敗");
            }
            //7
            stat.close();
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * JDBC的刪
     */
    @Test
    public void method4() {
        Connection conn = null;
        Statement stat = null;
        try {
            //2 alter + enter: 處理異常
            Class.forName("com.mysql.jdbc.Driver");
            //3
            conn = DriverManager.getConnection("jdbc:mysql:///web04", "root", "123");
            //4
            stat = conn.createStatement();
            //5
            String sql = "delete from users where uid = 6;";
            int num = stat.executeUpdate(sql);
            //6
            if(num > 0) {
                System.out.println("刪除成功");
            } else {
                System.out.println("刪除失敗");
            }
            //7
            stat.close();
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
11. JDBCUtils工具類的抽取
方式一: 普通抽取   
    public class JDBCUtils {
        //1. 構(gòu)造私有.
        
        //2. 注冊(cè)驅(qū)動(dòng), 靜態(tài)代碼塊實(shí)現(xiàn).
        
        //3. 獲取連接對(duì)象.
        
        //4. 釋放資源.    try-catch-finally 語(yǔ)句的嵌套實(shí)現(xiàn).
    }
    
    此時(shí), 雖然我們已經(jīng)成功的抽取出來(lái)了JDBCUtils工具類, 但是和一個(gè)開發(fā)原則相違背"對(duì)修改關(guān)閉, 對(duì)擴(kuò)展開放".
    例如: 如果我們想操作web05這個(gè)數(shù)據(jù)庫(kù)了, 就得修改工具類中url的寫法, 如果我們操作的數(shù)據(jù)庫(kù)的用戶名和密碼
    改變了, 我們也得修改工具類中username,password的寫法, 這樣做擴(kuò)展性較差.

    于是, 我們就想著如何解決這個(gè)問(wèn)題?
    
    能不能創(chuàng)建一個(gè)文件(配置文件), 里邊記錄的是各項(xiàng)配置信息, 然后由工具類讀取該配置文件的信息即可.
    這個(gè)配置文件就是:  **.properties
    
    
    Properties集合類:
        概述:  它是一個(gè)雙列集合, 鍵值都是String類型, 它是Hashtable集合的子類.
                //Properties集合是唯一可以直接和IO流相結(jié)合使用的集合類.
                //它可以直接從流中讀取數(shù)據(jù), 也可以直接寫數(shù)據(jù)到流中.
                
        成員方法:
            public void load(InputStream is);           //從流中讀取數(shù)據(jù)
            public void load(Reader r);                 //從流中讀取數(shù)據(jù)
            
            public void store(OutputStream os);         //寫數(shù)據(jù)到流中
            public void store(Writer w);                //寫數(shù)據(jù)到流中
            
            public String getProperty(String key);              //根據(jù)鍵獲取值
            public void setProperty(String key,String value);   //設(shè)置鍵值對(duì)
        
        
        
    
        面試題:
            Hashtable和HashMap的區(qū)別?
                HashMap: 線程不安全, 效率高, 可以存null值和null鍵.
                         JDK1.2出來(lái)來(lái).
                Hashtable: 線程安全, 效率低. 不可以存null值和null鍵.
                         JDK1.0出來(lái)的.
                整個(gè)Java命名規(guī)范是從: JDK1.2開始完善的.


方式二: 結(jié)合配置文件的使用
    public class JDBCUtils {
        //1. 構(gòu)造私有.
        
        //2. 定義變量, 記錄配置文件的信息.
        
        //3. 讀取配置文件, 并將讀取到的值賦值給變量.
        
        //4. 注冊(cè)驅(qū)動(dòng), 靜態(tài)代碼塊實(shí)現(xiàn).
        
        //5. 獲取連接對(duì)象.
        
        //6. 釋放資源.    try-catch-finally 語(yǔ)句的嵌套實(shí)現(xiàn).
    }
12. SQL注入攻擊問(wèn)題
概述:


代碼演示SQL注入攻擊問(wèn)題:


解決方案: PreparedStatement接口的預(yù)編譯, 占位符.

今日總結(jié):

1. JDBC的原生態(tài)代碼.
    
2. JDBC的優(yōu)化釋放資源的代碼
    
3. Properties的使用
    
4. 抽取JDBCUtils工具類
    
5. 解決SQL注入攻擊問(wèn)題
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末衡奥,一起剝皮案震驚了整個(gè)濱河市剪验,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌骨稿,老刑警劉巖鳖目,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扮叨,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡领迈,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)狸捅,“玉大人衷蜓,你說(shuō)我怎么就攤上這事〕竞龋” “怎么了磁浇?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)朽褪。 經(jīng)常有香客問(wèn)我置吓,道長(zhǎng),這世上最難降的妖魔是什么缔赠? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任衍锚,我火速辦了婚禮,結(jié)果婚禮上嗤堰,老公的妹妹穿的比我還像新娘戴质。我一直安慰自己,他們只是感情好踢匣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布告匠。 她就那樣靜靜地躺著,像睡著了一般离唬。 火紅的嫁衣襯著肌膚如雪后专。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天输莺,我揣著相機(jī)與錄音行贪,去河邊找鬼。 笑死模闲,一個(gè)胖子當(dāng)著我的面吹牛建瘫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播尸折,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼啰脚,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了实夹?” 一聲冷哼從身側(cè)響起橄浓,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎亮航,沒(méi)想到半個(gè)月后荸实,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡缴淋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年准给,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了泄朴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡露氮,死狀恐怖祖灰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情畔规,我是刑警寧澤局扶,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站叁扫,受9級(jí)特大地震影響三妈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜莫绣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一畴蒲、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧兔综,春花似錦饿凛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至锭亏,卻和暖如春纠吴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背慧瘤。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工戴已, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人锅减。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓糖儡,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親怔匣。 傳聞我的和親對(duì)象是個(gè)殘疾皇子握联,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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