java數(shù)據(jù)庫管理之jdbc

JDBC概念和數(shù)據(jù)庫驅(qū)動程序

  • A: JDBC概念和數(shù)據(jù)庫驅(qū)動程序
    • a: JDBC概述
      • JDBC(Java Data Base Connectivity,java數(shù)據(jù)庫連接)是一種用于執(zhí)行SQL語句的Java API,
        可以為多種關(guān)系數(shù)據(jù)庫提供統(tǒng)一訪問,它由一組用Java語言編寫的類和接口組成。是Java訪問數(shù)據(jù)庫的標(biāo)準(zhǔn)規(guī)范
      • JDBC提供了一種基準(zhǔn),據(jù)此可以構(gòu)建更高級的工具和接口,使數(shù)據(jù)庫開發(fā)人員能夠編寫數(shù)據(jù)庫應(yīng)用程序。
      • JDBC需要連接驅(qū)動,驅(qū)動是兩個設(shè)備要進(jìn)行通信,滿足一定通信數(shù)據(jù)格式,數(shù)據(jù)格式由設(shè)備提供商規(guī)定,
        設(shè)備提供商為設(shè)備提供驅(qū)動軟件,通過軟件可以與該設(shè)備進(jìn)行通信。
      • 我們使用的是mysql的驅(qū)動mysql-connector-java-5.1.39-bin.jar
    • b: 總結(jié)
      • JDBC是java提供給開發(fā)人員的一套操作數(shù)據(jù)庫的接口
      • 數(shù)據(jù)庫驅(qū)動就是實現(xiàn)該接口的實現(xiàn)類

JDBC原理

* a: 描述
    * Java提供訪問數(shù)據(jù)庫規(guī)范稱為JDBC,而生產(chǎn)廠商提供規(guī)范的實現(xiàn)類稱為驅(qū)動
    * JDBC是接口,驅(qū)動是接口的實現(xiàn),沒有驅(qū)動將無法完成數(shù)據(jù)庫連接,從而不能操作數(shù)據(jù)庫!
        每個數(shù)據(jù)庫廠商都需要提供自己的驅(qū)動,用來連接自己公司的數(shù)據(jù)庫,也就是說驅(qū)動一般都由數(shù)據(jù)庫生成廠商提供。

準(zhǔn)備數(shù)據(jù)

* A: 準(zhǔn)備數(shù)據(jù)
    * a: 創(chuàng)建數(shù)據(jù)庫和表結(jié)構(gòu)
        #創(chuàng)建數(shù)據(jù)庫
        create database mybase;
        #使用數(shù)據(jù)庫
        use mybase;
        ###創(chuàng)建分類表
        create table sort(
          sid int PRIMARY KEY AUTO_INCREMENT,
          sname varchar(100),
          sprice DOUBLE,
          sdesc VARCHAR(500)
        );
        
    * b: 向表中插入數(shù)據(jù)
        #初始化數(shù)據(jù)
        insert into sort(sname,sprice,sdesc) values('家電',2000, '優(yōu)惠的促銷');
        insert into sort(sname,sprice,sdesc) values('家具',8900, '家具價格上調(diào),原材料漲價');
        insert into sort(sname,sprice,sdesc) values('兒童玩具',290, '賺家長的錢');
        insert into sort(sname,sprice,sdesc) values('生鮮',500.99, '生鮮商品');
        insert into sort(sname,sprice,sdesc) values('服裝',24000, '換季銷售');
        insert into sort(sname,sprice,sdesc) values('洗滌',50, '洗發(fā)水促銷');         

JDBC的開發(fā)步驟

* A: JDBC的開發(fā)步驟
    * a: 步驟介紹
        1.注冊驅(qū)動
            告知JVM使用的是哪一個數(shù)據(jù)庫的驅(qū)動
        2.獲得連接
            使用JDBC中的類,完成對MySQL數(shù)據(jù)庫的連接
        3.獲得語句執(zhí)行平臺
            通過連接對象獲取對SQL語句的執(zhí)行者對象
        4.執(zhí)行sql語句
            使用執(zhí)行者對象,向數(shù)據(jù)庫執(zhí)行SQL語句
            獲取到數(shù)據(jù)庫的執(zhí)行后的結(jié)果
        5.處理結(jié)果
        6.釋放資源  一堆close()

導(dǎo)入mysql數(shù)據(jù)庫驅(qū)動程序jar包

* A: 導(dǎo)入mysql數(shù)據(jù)庫驅(qū)動程序jar包
    * a: 步驟
        * 創(chuàng)建lib目錄,用于存放當(dāng)前項目需要的所有jar包
        * 選擇jar包,右鍵執(zhí)行build path / Add to Build Path

注冊數(shù)據(jù)庫驅(qū)動程序

* A: 注冊數(shù)據(jù)庫驅(qū)動程序
    * a: 案例代碼
        public class JDBCDemo {
            public static void main(String[] args)throws ClassNotFoundException,SQLException{
                //1.注冊驅(qū)動 反射技術(shù),將驅(qū)動類加入到內(nèi)容
                // 使用java.sql.DriverManager類靜態(tài)方法 registerDriver(Driver driver)
                // Diver是一個接口,參數(shù)傳遞,MySQL驅(qū)動程序中的實現(xiàn)類
                //DriverManager.registerDriver(new Driver());
                //驅(qū)動類源代碼,注冊2次驅(qū)動程序
                Class.forName("com.mysql.jdbc.Driver");                    
            }
        }

        
    

獲取數(shù)據(jù)庫的連接對象

* A:獲取數(shù)據(jù)庫的連接對象
    * a: 案例代碼
        public class JDBCDemo {
            public static void main(String[] args)throws ClassNotFoundException,SQLException{
                //1.注冊驅(qū)動 反射技術(shù),將驅(qū)動類加入到內(nèi)容
                // 使用java.sql.DriverManager類靜態(tài)方法 registerDriver(Driver driver)
                // Diver是一個接口,參數(shù)傳遞,MySQL驅(qū)動程序中的實現(xiàn)類
                //DriverManager.registerDriver(new Driver());
                //驅(qū)動類源代碼,注冊2次驅(qū)動程序
                Class.forName("com.mysql.jdbc.Driver");
                
                //2.獲得數(shù)據(jù)庫連接  DriverManager類中靜態(tài)方法
                //static Connection getConnection(String url, String user, String password)  
                //返回值是Connection接口的實現(xiàn)類,在mysql驅(qū)動程序
                //url: 數(shù)據(jù)庫地址  jdbc:mysql://連接主機(jī)IP:端口號//數(shù)據(jù)庫名字
                String url = "jdbc:mysql://localhost:3306/mybase?useUnicode=true&characterEncoding=UTF-8";
                //用戶名和密碼用自己的
                String username="root";
                String password="123";
                Connection con = DriverManager.getConnection(url, username, password);
                System.out.println(con);                    
            }
        }

獲取SQL語句的執(zhí)行對象

* A: 獲取SQL語句的執(zhí)行對象
    * a: 案例代碼
        public class JDBCDemo {
            public static void main(String[] args)throws ClassNotFoundException,SQLException{
                //1.注冊驅(qū)動 反射技術(shù),將驅(qū)動類加入到內(nèi)容
                // 使用java.sql.DriverManager類靜態(tài)方法 registerDriver(Driver driver)
                // Diver是一個接口,參數(shù)傳遞,MySQL驅(qū)動程序中的實現(xiàn)類
                //DriverManager.registerDriver(new Driver());
                //驅(qū)動類源代碼,注冊2次驅(qū)動程序
                Class.forName("com.mysql.jdbc.Driver");
                
                //2.獲得數(shù)據(jù)庫連接  DriverManager類中靜態(tài)方法
                //static Connection getConnection(String url, String user, String password)  
                //返回值是Connection接口的實現(xiàn)類,在mysql驅(qū)動程序
                //url: 數(shù)據(jù)庫地址  jdbc:mysql://連接主機(jī)IP:端口號//數(shù)據(jù)庫名字
                String url = "jdbc:mysql://localhost:3306/mybase?useUnicode=true&characterEncoding=UTF-8";
                String username="root";
                String password="123";
                Connection con = DriverManager.getConnection(url, username, password);
                
                //3.獲得語句執(zhí)行平臺, 通過數(shù)據(jù)庫連接對象,獲取到SQL語句的執(zhí)行者對象
                // con對象調(diào)用方法   Statement createStatement() 獲取Statement對象,將SQL語句發(fā)送到數(shù)據(jù)庫
                // 返回值是 Statement接口的實現(xiàn)類對象,,在mysql驅(qū)動程序
                Statement stat = con.createStatement();
                System.out.println(stat);
            }
        }

執(zhí)行insert語句獲取結(jié)果集

   * a: 案例代碼
        public class JDBCDemo {
            public static void main(String[] args)throws ClassNotFoundException,SQLException{
                //1.注冊驅(qū)動 反射技術(shù),將驅(qū)動類加入到內(nèi)容
                // 使用java.sql.DriverManager類靜態(tài)方法 registerDriver(Driver driver)
                // Diver是一個接口,參數(shù)傳遞,MySQL驅(qū)動程序中的實現(xiàn)類
                //DriverManager.registerDriver(new Driver());
                //驅(qū)動類源代碼,注冊2次驅(qū)動程序
                Class.forName("com.mysql.jdbc.Driver");
                
                //2.獲得數(shù)據(jù)庫連接  DriverManager類中靜態(tài)方法
                //static Connection getConnection(String url, String user, String password)  
                //返回值是Connection接口的實現(xiàn)類,在mysql驅(qū)動程序
                //url: 數(shù)據(jù)庫地址  jdbc:mysql://連接主機(jī)IP:端口號//數(shù)據(jù)庫名字
                String url = "jdbc:mysql://localhost:3306/mybase?useUnicode=true&characterEncoding=UTF-8";
                String username="root";
                String password="123";
                Connection con = DriverManager.getConnection(url, username, password);
                
                //3.獲得語句執(zhí)行平臺, 通過數(shù)據(jù)庫連接對象,獲取到SQL語句的執(zhí)行者對象
                // con對象調(diào)用方法   Statement createStatement() 獲取Statement對象,將SQL語句發(fā)送到數(shù)據(jù)庫
                // 返回值是 Statement接口的實現(xiàn)類對象,,在mysql驅(qū)動程序
                Statement stat = con.createStatement();
                //    4.執(zhí)行sql語句
                // 通過執(zhí)行者對象調(diào)用方法執(zhí)行SQL語句,獲取結(jié)果
                // int executeUpdate(String sql)  執(zhí)行數(shù)據(jù)庫中的SQL語句, insert delete update
                // 返回值int,操作成功數(shù)據(jù)表多少行
                int row = stat.executeUpdate
                        ("INSERT INTO sort(sname,sprice,sdesc) VALUES('汽車用品',50000,'瘋狂漲價')");
                System.out.println(row);
                
                //6.釋放資源  一堆close()
                stat.close();
                con.close();
            }
        }
        

執(zhí)行select語句獲取結(jié)果集

* a: 案例代碼
        public class JDBCDemo1 {
            public static void main(String[] args) throws Exception{
                //1. 注冊驅(qū)動
                Class.forName("com.mysql.jdbc.Driver");
                //2. 獲取連接對象
                String url = "jdbc:mysql://localhost:3306/mybase?useUnicode=true&characterEncoding=UTF-8";
                String username="root";
                String password="123";
                Connection con = DriverManager.getConnection(url, username, password);
                //3 .獲取執(zhí)行SQL 語句對象
                Statement stat = con.createStatement();
                // 拼寫查詢的SQL
                String sql = "SELECT * FROM sort";
                //4. 調(diào)用執(zhí)行者對象方法,執(zhí)行SQL語句獲取結(jié)果集
                // ResultSet executeQuery(String sql)  執(zhí)行SQL語句中的select查詢
                // 返回值ResultSet接口的實現(xiàn)類對象,實現(xiàn)類在mysql驅(qū)動中
                ResultSet rs = stat.executeQuery(sql);
                //5 .處理結(jié)果集
                // ResultSet接口方法 boolean next() 返回true,有結(jié)果集,返回false沒有結(jié)果集
                while(rs.next()){
                    //獲取每列數(shù)據(jù),使用是ResultSet接口的方法 getXX方法參數(shù)中,建議寫String列名
                    System.out.println(rs.getInt("sid")+"   "+rs.getString("sname")+
                            "   "+rs.getDouble("sprice")+"   "+rs.getString("sdesc"));
                }
                
                rs.close();
                stat.close();
                con.close();
            }
        }

SQL注入攻擊

  * a: 注入問題
        * 假設(shè)有登錄案例SQL語句如下:
        * SELECT * FROM 用戶表 WHERE NAME = 用戶輸入的用戶名 AND PASSWORD = 用戶輸?shù)拿艽a;
        * 此時,當(dāng)用戶輸入正確的賬號與密碼后,查詢到了信息則讓用戶登錄。
            但是當(dāng)用戶輸入的賬號為XXX 密碼為:XXX’  OR ‘a(chǎn)’=’a'時,則真正執(zhí)行的代碼變?yōu)椋?            * SELECT * FROM 用戶表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’  OR ’a’=’a’;
        * 此時,上述查詢語句時永遠(yuǎn)可以查詢出結(jié)果的。那么用戶就直接登錄成功了,顯然我們不希望看到這樣的結(jié)果,這便是SQL注入問題。
    * b: 案例演示
        CREATE TABLE users(
             id INT PRIMARY KEY AUTO_INCREMENT,
             username VARCHAR(100),
             PASSWORD VARCHAR(100)
        );

        INSERT INTO users (username,PASSWORD) VALUES ('a','1'),('b','2');

        SELECT * FROM users;

        -- 登錄查詢
        SELECT * FROM users WHERE username='dsfsdfd' AND PASSWORD='wrethiyu'
        OR 1=1

        SELECT * FROM users WHERE username='a' AND PASSWORD='1' OR 1=1

          鍵盤錄入:
        1
        1'OR' 1=1

SQL注入攻擊用戶登錄案例

* a: 案例代碼
        public class JDBCDemo2 {
            public static void main(String[] args)throws Exception {
                Class.forName("com.mysql.jdbc.Driver");
                String url = "jdbc:mysql://localhost:3296/mybase";
                String username = "root";
                String password = "123";
                Connection con = DriverManager.getConnection(url, username, password);
                Statement stat = con.createStatement();
                
                Scanner sc = new Scanner(System.in);
                String user = sc.nextLine();
                String pass = sc.nextLine();
                
                //執(zhí)行SQL語句,數(shù)據(jù)表,查詢用戶名和密碼,如果存在,登錄成功,不存在登錄失敗
        //        String sql = "SELECT * FROM users WHERE username='dsfsdfd' AND PASSWORD='wrethiyu' OR 1=1";
                String sql = "SELECT * FROM users WHERE username='"+user+"' AND PASSWORD='"+pass+"'";
                System.out.println(sql);
                ResultSet rs = stat.executeQuery(sql);
                while(rs.next()){
                    System.out.println(rs.getString("username")+"   "+rs.getString("password"));
                }
                
                rs.close();
                stat.close();
                con.close();
            }
        }

    

PrepareStatement接口預(yù)編譯SQL語句

 * a: 預(yù)處理對象
        * 使用PreparedStatement預(yù)處理對象時,建議每條sql語句所有的實際參數(shù),都使用逗號分隔。
        * String sql = "insert into sort(sid,sname) values(?,?)";;
        * PreparedStatement預(yù)處理對象代碼:
        * PreparedStatement psmt = conn.prepareStatement(sql)
        
    * b: 執(zhí)行SQL語句的方法介紹
        * int executeUpdate(); --執(zhí)行insert update delete語句.
        * ResultSet executeQuery(); --執(zhí)行select語句.
        * boolean execute(); --執(zhí)行select返回true 執(zhí)行其他的語句返回false.
    * c: 設(shè)置實際參數(shù)
        * void setXxx(int index, Xxx xx) 將指定參數(shù)設(shè)置為給定Java的xx值。在將此值發(fā)送到數(shù)據(jù)庫時,驅(qū)動程序?qū)⑺D(zhuǎn)換成一個 SQL Xxx類型值。
        * 例如:
            * setString(2, "家用電器") 把SQL語句中第2個位置的占位符? 替換成實際參數(shù) "家用電器"
    * d: 案例代碼
        /*
         *  Java程序?qū)崿F(xiàn)用戶登錄,用戶名和密碼,數(shù)據(jù)庫檢查
         *  防止注入攻擊
         *  Statement接口實現(xiàn)類,作用執(zhí)行SQL語句,返回結(jié)果集
         *  有一個子接口PreparedStatement  (SQL預(yù)編譯存儲,多次高效的執(zhí)行SQL) 
         *  PreparedStatement的實現(xiàn)類數(shù)據(jù)庫的驅(qū)動中,如何獲取接口的實現(xiàn)類
         *  
         *  是Connection數(shù)據(jù)庫連接對象的方法
         *  PreparedStatement prepareStatement(String sql) 
                  
         */
        public class JDBCDemo3 {
            public static void main(String[] args)throws Exception {
                Class.forName("com.mysql.jdbc.Driver");
                String url = "jdbc:mysql://localhost:3296/mybase";
                String username = "root";
                String password = "123";
                Connection con = DriverManager.getConnection(url, username, password);
                Scanner sc = new Scanner(System.in);
                String user = sc.nextLine();
                String pass = sc.nextLine();
                
                //執(zhí)行SQL語句,數(shù)據(jù)表,查詢用戶名和密碼,如果存在,登錄成功,不存在登錄失敗
                String sql = "SELECT * FROM users WHERE username=? AND PASSWORD=?";
                //調(diào)用Connection接口的方法prepareStatement,獲取PrepareStatement接口的實現(xiàn)類
                //方法中參數(shù),SQL語句中的參數(shù)全部采用問號占位符
                PreparedStatement pst =  con.prepareStatement(sql);
                System.out.println(pst);
                //調(diào)用pst對象set方法,設(shè)置問號占位符上的參數(shù)
                pst.setObject(1, user);
                pst.setObject(2, pass);
                
                //調(diào)用方法,執(zhí)行SQL,獲取結(jié)果集
                ResultSet rs = pst.executeQuery();
                while(rs.next()){
                    System.out.println(rs.getString("username")+"   "+rs.getString("password"));
                }
                
                rs.close();
                pst.close();
                con.close();
            }
        }

PrepareStatement接口預(yù)編譯SQL語句執(zhí)行修改

   * 案例代碼
        /*
         *  使用PrepareStatement接口,實現(xiàn)數(shù)據(jù)表的更新操作
         */
        public class JDBCDemo {
            public static void main(String[] args) throws Exception{
                Class.forName("com.mysql.jdbc.Driver");
                String url = "jdbc:mysql://localhost:3296/mybase";
                String username="root";
                String password="123";
                Connection con = DriverManager.getConnection(url, username, password);    
                
                //拼寫修改的SQL語句,參數(shù)采用?占位
                String sql = "UPDATE sort SET sname=?,sprice=? WHERE sid=?";
                //調(diào)用數(shù)據(jù)庫連接對象con的方法prepareStatement獲取SQL語句的預(yù)編譯對象
                PreparedStatement pst = con.prepareStatement(sql);
                //調(diào)用pst的方法setXXX設(shè)置?占位
                pst.setObject(1, "汽車美容");
                pst.setObject(2, 49988);
                pst.setObject(3, 7);
                //調(diào)用pst方法執(zhí)行SQL語句
                pst.executeUpdate();
                
                pst.close();
                con.close();
            }
        }

PrepareStatement接口預(yù)編譯SQL語句執(zhí)行查詢

 * a: 案例代碼
        /*
         *  PrepareStatement接口實現(xiàn)數(shù)據(jù)表的查詢操作
         */
        public class JDBCDemo1 {
            public static void main(String[] args) throws Exception{
                Class.forName("com.mysql.jdbc.Driver");
                String url = "jdbc:mysql://localhost:3296/mybase";
                String username="root";
                String password="123";
                Connection con = DriverManager.getConnection(url, username, password);    
                
                String sql = "SELECT * FROM sort";
                
                PreparedStatement pst = con.prepareStatement(sql);
                
                //調(diào)用pst對象的方法,執(zhí)行查詢語句,Select
                ResultSet rs=pst.executeQuery();
                while(rs.next()){
                    System.out.println(rs.getString("sid")+"  "+rs.getString("sname")+"  "+rs.getString("sprice")+"  "+rs.getString("sdesc"));
                }
                rs.close();
                pst.close();
                con.close();
            }
        }

JDBC的工具類和測試

* a: 案例代碼
        //JDBCUtils工具類代碼
        public class JDBCUtils {
            private JDBCUtils(){}
            private static Connection con ;
            
            static{
                try{
                    Class.forName("com.mysql.jdbc.Driver");
                    String url = "jdbc:mysql://localhost:3296/mybase";
                    String username="root";
                    String password="123";
                    con = DriverManager.getConnection(url, username, password);
                }catch(Exception ex){
                    throw new RuntimeException(ex+"數(shù)據(jù)庫連接失敗");
                }
            }
            
            /*
             * 定義靜態(tài)方法,返回數(shù)據(jù)庫的連接對象
             */
            public static Connection getConnection(){
                return con;
            }
            
            
            public static void close(Connection con,Statement stat){
                 
                 if(stat!=null){
                     try{
                         stat.close();
                     }catch(SQLException ex){}
                 }
                 
                 if(con!=null){
                     try{
                         con.close();
                     }catch(SQLException ex){}
                 }
                 
            }
            
            
            public static void close(Connection con,Statement stat , ResultSet rs){
                 if(rs!=null){
                     try{
                         rs.close();
                     }catch(SQLException ex){}
                 }
                 
                 if(stat!=null){
                     try{
                         stat.close();
                     }catch(SQLException ex){}
                 }
                 
                 if(con!=null){
                     try{
                         con.close();
                     }catch(SQLException ex){}
                 }
                 
            }
        }
    //測試JDBCUtils工具類的代碼
    public class TestJDBCUtils {
        public static void main(String[] args)throws Exception {
            Connection con = JDBCUtils.getConnection();
            PreparedStatement pst = con.prepareStatement("SELECT sname FROM sort");
            ResultSet rs = pst.executeQuery();
            while(rs.next()){
                System.out.println(rs.getString("sname"));
            }
            JDBCUtils.close(con, pst, rs);
        }
    }
    

jdbc事務(wù)處理

案例:轉(zhuǎn)賬操作,輸入;兩個用戶名,然后輸出一個轉(zhuǎn)賬金額,操作為:第一個用戶給第二個用戶轉(zhuǎn)賬指定的金額。

在金額從A用戶轉(zhuǎn)出完了,再轉(zhuǎn)入到B賬戶的過程中如果系統(tǒng)出現(xiàn)故障,那么金額就不會轉(zhuǎn)入到B賬戶了。但是A事務(wù)已經(jīng)提交(只要執(zhí)行了DML操作jdbc默認(rèn)就是自動提交事務(wù)的)。這就造成了金額憑空丟失的問題。所以,需要讓所有的操作在同一個事務(wù)中,中間任何一部出現(xiàn)問題就需要事務(wù)回滾,能執(zhí)行到最后才能進(jìn)行事務(wù)提交。
基本實現(xiàn):

try{
//關(guān)閉自動提交
    //操作1
    //操作2
    //提交事務(wù)
}catch(){
    //回滾事務(wù)
}
這樣做就能保障一組操作的完整性.
public class JDBCTrans {
    public static void main(String[] args) {
        Connection connection = null;
        try {
            Scanner scanner = new Scanner(System.in);
            System.out.println("輸入轉(zhuǎn)出賬號:");
            String out = scanner.nextLine();
            System.out.println("輸入轉(zhuǎn)入賬號:");
            String in = scanner.nextLine();
            System.out.println("輸入轉(zhuǎn)賬金額");
            int account = scanner.nextInt();

            connection=DBUtil.getConnection();
            //設(shè)置事務(wù)不自動提交
            connection.setAutoCommit(false);
            //轉(zhuǎn)出
            String outSql="UPDATE userinfo "
                    + "SET account=account-? "
                    + "WHERE username=?";

            PreparedStatement preparedStatement = connection.prepareStatement(outSql);

            preparedStatement.setInt(1, account);
            preparedStatement.setString(2, out);
            int m = preparedStatement.executeUpdate();
            System.out.println("---");
            if(m>0){
                System.out.println("轉(zhuǎn)出成功");
            }else {
                System.out.println("轉(zhuǎn)出失敗");
                //不再進(jìn)行轉(zhuǎn)入
                return;
            }
            //轉(zhuǎn)入
            String inSql="UPDATE userinfo "
                    + "SET account=account+?"
                    + "WHERE username=?";

            preparedStatement = connection.prepareStatement(inSql);
            preparedStatement.setInt(1, account);
            preparedStatement.setString(2, in);
            int n = preparedStatement.executeUpdate();
            if(n>0){
                System.out.println("轉(zhuǎn)入成功");
                connection.commit();
            }else {
                System.out.println("轉(zhuǎn)入失敗");
                //回滾事務(wù)
                connection.rollback();
            }

        } catch (Exception e) {
            //出現(xiàn)異?;貪L事務(wù)
            try {
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            DBUtil.closeConnection();
        }
    }
}

jdbc之批處理

批操作可以一次性向數(shù)據(jù)庫端發(fā)送若干SQL語句,從而減少與數(shù)據(jù)庫服務(wù)端的網(wǎng)絡(luò)通信,提高執(zhí)行效率。
當(dāng)大批量執(zhí)行SQL語句時,影響效率的2個因素:
1:事務(wù),事務(wù)越多速度越慢(事務(wù)最好一次提交);
2:網(wǎng)絡(luò)調(diào)用,網(wǎng)絡(luò)調(diào)用越多速度越慢(這里可以使用緩存解決);
需求:向數(shù)據(jù)庫中userinfo表插入10000條數(shù)據(jù)
自動提交事務(wù),不添加緩存測試:

public class JDBCBatch {
    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        try {
            connection = DBUtil.getConnection();
            statement = connection.createStatement();
            long start =new Date().getTime();
            System.out.println("開始前:"+start);
            for (int i = 0; i < 10000; i++) {
                String sql="INSERT INTO userinfo "
                        + "VALUES "
                        + "(seq_userinfo_id.NEXTVAL,'test"+i+"','123456',"
                        + "5000,'test"+i+"@tedu.cn')";
                //立刻將SQL發(fā)送至數(shù)據(jù)庫服務(wù)端
                statement.executeUpdate(sql);
            }

            System.out.println("結(jié)束用時:"+(new Date().getTime()-start));

        } catch (Exception e) {

        }finally {
            DBUtil.closeConnection();
        }
    }
}
輸出:
開始前:1502871180710
結(jié)束用時:10757
public class JDBCDemo2 {
    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement pStatement;
        try {
            connection = DBUtil.getConnection();
            connection.setAutoCommit(false);
            String sql="INSERT INTO userinfo "
                    + "VALUES "
                    + "(seq_userinfo_id.NEXTVAL,?,'123456',5000"
                    + ",?)";
            pStatement = connection.prepareStatement(sql);
            long time = new Date().getTime();
            for (int i = 0; i < 10000; i++) {
                pStatement.setString(1, "aa"+i);
                pStatement.setString(2, "scu@qq.com"+i);
                pStatement.addBatch();
            }
            pStatement.executeBatch();
            System.out.println("用時:"+(new Date().getTime() - time));
            //清空本地緩存
            pStatement.clearBatch();
            connection.commit();

        } catch (Exception e) {
            try {
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            DBUtil.closeConnection();
        }
    }
}
輸出:
用時:103

數(shù)據(jù)表數(shù)據(jù)存儲對象

* b: 案例代碼
        //定義實體類Sort
        public class Sort {
            private int sid;
            private String sname;
            private double sprice;
            private String sdesc;
            public Sort(int sid, String sname, double sprice, String sdesc) {
                this.sid = sid;
                this.sname = sname;
                this.sprice = sprice;
                this.sdesc = sdesc;
            }
            public Sort(){}
            public int getSid() {
                return sid;
            }
            public void setSid(int sid) {
                this.sid = sid;
            }
            public String getSname() {
                return sname;
            }
            public void setSname(String sname) {
                this.sname = sname;
            }
            public double getSprice() {
                return sprice;
            }
            public void setSprice(double sprice) {
                this.sprice = sprice;
            }
            public String getSdesc() {
                return sdesc;
            }
            public void setSdesc(String sdesc) {
                this.sdesc = sdesc;
            }
            @Override
            public String toString() {
                return "Sort [sid=" + sid + ", sname=" + sname + ", sprice=" + sprice + ", sdesc=" + sdesc + "]";
            }                
        }
        
        /*
         *  JDBC讀取數(shù)據(jù)表sort,每行數(shù)據(jù)封裝到Sort類的對象中
         *  很多個Sort類對象,存儲到List集合中
         */
        public class JDBCDemo {
            public static void main(String[] args) throws Exception{
                //使用JDBC工具類,直接獲取數(shù)據(jù)庫連接對象
                Connection con = JDBCUtils.getConnection();
                //連接獲取數(shù)據(jù)庫SQL語句執(zhí)行者對象
                PreparedStatement pst = con.prepareStatement("SELECT * FROM sort");
                //調(diào)用查詢方法,獲取結(jié)果集
                ResultSet rs = pst.executeQuery();
                //創(chuàng)建集合對象
                List<Sort> list = new ArrayList<Sort>();
                while(rs.next()){
                    //獲取到每個列數(shù)據(jù),封裝到Sort對象中
                    Sort s = new Sort(rs.getInt("sid"),rs.getString("sname"),rs.getDouble("sprice"),rs.getString("sdesc"));
                    //封裝的Sort對象,存儲到集合中
                    list.add(s);
                }
                JDBCUtils.close(con, pst, rs);
                //遍歷List集合
                for(Sort s : list){
                    System.out.println(s);
                }
            }
        }

properties配置文件

    * a: 相關(guān)介紹
        * 開發(fā)中獲得連接的4個參數(shù)(驅(qū)動、URL、用戶名、密碼)通常都存在配置文件中,方便后期維護(hù),程序如果需要更換數(shù)據(jù)庫,
            只需要修改配置文件即可。
        * 通常情況下,我們習(xí)慣使用properties文件,此文件我們將做如下要求:
            1.    文件位置:任意,建議src下
            2.    文件名稱:任意,擴(kuò)展名為properties
            3.    文件內(nèi)容:一行一組數(shù)據(jù),格式是“key=value”.
                a)    key命名自定義,如果是多個單詞,習(xí)慣使用點分隔。例如:jdbc.driver
                b)    value值不支持中文,如果需要使用非英文字符,將進(jìn)行unicode轉(zhuǎn)換。

properties文件的創(chuàng)建和編寫

 * a: properties文件的創(chuàng)建
        * src路徑下建立database.properties(其實就是一個文本文件)
    * b: properties文件的編寫(內(nèi)容如下)
        driverClass=com.mysql.jdbc.Driver
        url=jdbc:mysql://localhost:3296/mybase
        username=root
        password=123        

加載配置文件

  * a: 案例代碼        
        /*
         *  加載properties配置文件
         *  IO讀取文件,鍵值對存儲到集合
         *  從集合中以鍵值對方式獲取數(shù)據(jù)庫的連接信息,完成數(shù)據(jù)庫的連接
         */
        public class PropertiesDemo {
            public static void main(String[] args) throws Exception{
                FileInputStream fis = new FileInputStream("database.properties");
                System.out.println(fis);
                //使用類的加載器
                InputStream in = PropertiesDemo.class.getClassLoader().getResourceAsStream("database.properties");
                System.out.println(in);
                Properties pro = new Properties();
                pro.load(in);
                System.out.println(in);                    
            }
        }

通過配置文件連接數(shù)據(jù)庫

 * a: 案例代碼
        /*
         *  加載properties配置文件
         *  IO讀取文件,鍵值對存儲到集合
         *  從集合中以鍵值對方式獲取數(shù)據(jù)庫的連接信息,完成數(shù)據(jù)庫的連接
         */
        public class PropertiesDemo {
            public static void main(String[] args) throws Exception{
              
                //使用類的加載器
                InputStream in = PropertiesDemo.class.getClassLoader().getResourceAsStream("database.properties");
                System.out.println(in);
                Properties pro = new Properties();
                pro.load(in);
                //獲取集合中的鍵值對
                String driverClass=pro.getProperty("driverClass");
                String url = pro.getProperty("url");
                String username = pro.getProperty("username");
                String password = pro.getProperty("password");
                Class.forName(driverClass);
                Connection con = DriverManager.getConnection(url, username, password);
                System.out.println(con);
                
            }
        }

讀取配置文件的工具類

 * a: 案例代碼
        /*
         *  編寫數(shù)據(jù)庫連接的工具類,JDBC工具類
         *  獲取連接對象采用讀取配置文件方式
         *  讀取文件獲取連接,執(zhí)行一次,static{}
         */
        public class JDBCUtilsConfig {
            private static Connection con ;
            private static String driverClass;
            private static String url;
            private static String username;
            private static String password;
            
            static{
                try{
                    readConfig();
                    Class.forName(driverClass);
                    con = DriverManager.getConnection(url, username, password);
                }catch(Exception ex){
                    throw new RuntimeException("數(shù)據(jù)庫連接失敗");
                }
            }
            
            private static void readConfig()throws Exception{
                InputStream in = JDBCUtilsConfig.class.getClassLoader().getResourceAsStream("database.properties");
                 Properties pro = new Properties();
                 pro.load(in);
                 driverClass=pro.getProperty("driverClass");
                 url = pro.getProperty("url");
                 username = pro.getProperty("username");
                 password = pro.getProperty("password");
            }
            
            
            public static Connection getConnection(){
                return con;
            }
            
        }            
        

測試工具類

    * a: 案例代碼
        public class TestJDBCUtils {
            public static void main(String[] args) {
                Connection con = JDBCUtilsConfig.getConnection();
                System.out.println(con);
            }
        }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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