久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

JDBC加強(qiáng)

 印度阿三17 2019-11-01

一,、使用PreparedStatement預(yù)編譯語句防止SQL注入

什么是SQL注入?

所謂SQL注入,,就是通過把SQL命令插入到Web表單提交或輸入域名或頁(yè)面請(qǐng)求的查詢字符串,,最終達(dá)到欺騙服務(wù)器執(zhí)行惡意的SQL命令,。

舉個(gè)例子:假如我們登錄時(shí)執(zhí)行的SQL語句為:select *from user where username='USERNAME' and password='PASSWORD';

但是我們可以把USERNAME填寫為"tom';-- ",(注意--后有空格),PASSWORD隨便寫(假設(shè)這里寫123),,這樣SQL語句就成了select *from user where username='tom';-- ' and password='123';

"-- "后的內(nèi)容就被注釋掉,,現(xiàn)在就算密碼不正確也能查詢到相應(yīng)的結(jié)果。利用SQL注入可以實(shí)現(xiàn)數(shù)據(jù)的盜取

在Java中使用PreparedStatement類防止SQL注入

防SQL注入的方法有很多,,使用預(yù)編譯語句是一種簡(jiǎn)單有效的方式

下面介紹如何使用這種方式來操作數(shù)據(jù)庫(kù)

我已經(jīng)在本地?cái)?shù)據(jù)庫(kù)mydb中創(chuàng)建了一個(gè)user表,,并在表中插入數(shù)據(jù)

現(xiàn)在我們使用字符串拼接的方式來構(gòu)造一個(gè)SQL語句,并在mysql客戶端執(zhí)行此SQL語句,,結(jié)果如下:

通過圖中我們發(fā)現(xiàn)這種方式SQL注入成功

下面使用預(yù)編譯SQL語句的方式來執(zhí)行此SQL語句

     String url = "jdbc:mysql://localhost:3306/mydb";
     String user = "root";
     String password = "root";
     String username = "杜若' or 1=1; -- ";  //'-- ' 是sql中的注釋符號(hào)(注意后面的空格)
     String pwd = "000";
    Class.forName("com.mysql.jdbc.Driver");
    
    Connection  connection  = DriverManager.getConnection(url,user,password);
    
     //構(gòu)造sql語句
    String sql = "select *from user where username=? and pwd =?";
    
    
    PreparedStatement pstmt = connection.prepareStatement(sql);
    
    pstmt.setString(1, username);
    pstmt.setString(2, pwd);
    
    ResultSet rs = pstmt.executeQuery();
    if(rs.next()){
        do{
            String username = rs.getString(2);
            String pwd = rs.getString(3);
            
            System.out.println(username ":" pwd);
        }while(rs.next());
    }else{
        System.out.println("未查到相應(yīng)的結(jié)果");
    }
    
    
    
    if(rs!=null){
        rs.close();
    }
    if(pstmt!=null){
        pstmt.close();
    }
    if(connection!=null){
        connection.close();
    }

測(cè)試運(yùn)行之后的結(jié)果

這樣已經(jīng)達(dá)到了防SQL注入的目的

那為什么它這樣處理就能預(yù)防SQL注入提高安全性呢,?其實(shí)是因?yàn)镾QL語句在程序運(yùn)行前已經(jīng)進(jìn)行了預(yù)編譯,在程序運(yùn)行時(shí)第一次操作數(shù)據(jù)庫(kù)之前,,SQL語句已經(jīng)被數(shù)據(jù)庫(kù)分析,編譯和優(yōu)化,,對(duì)應(yīng)的執(zhí)行計(jì)劃也會(huì)緩存下來并允許數(shù)據(jù)庫(kù)已參數(shù)化的形式進(jìn)行查詢,,當(dāng)運(yùn)行時(shí)動(dòng)態(tài)地把參數(shù)傳給PreprareStatement時(shí),即使參數(shù)里有敏感字符如 or '1=1'也數(shù)據(jù)庫(kù)會(huì)作為一個(gè)參數(shù)一個(gè)字段的屬性值來處理而不會(huì)作為一個(gè)SQL指令

二,,獲取插入自增長(zhǎng)值

有時(shí)候在插入一條記錄的時(shí)候,,我們需要獲取插入這條數(shù)據(jù)的自增長(zhǎng)值,以便在其他地方使用

直接上代碼

//獲取插入自增長(zhǎng)
public class Demo1 {
    private String user="root";
    private String password="root";
    private String url="jdbc:mysql://localhost:3306/mydb";
    
    @Test
    public void test1() throws Exception{
        Class.forName("com.mysql.jdbc.Driver");
        Connection connection = DriverManager.getConnection(url, user, password);
        String sql = "insert into user(username,pwd) values(?,?)";
        //第二個(gè)參數(shù)是Statement類中的一個(gè)常量,,指示是否應(yīng)該返回自動(dòng)生成的鍵的標(biāo)志
        PreparedStatement pstmt = connection.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
        
        pstmt.setString(1, "mary");
        pstmt.setString(2, "123456");
        
        pstmt.executeUpdate();
        
        ResultSet rs = pstmt.getGeneratedKeys();
        if(rs.next()){
            int key = rs.getInt(1);
            System.out.println(key);
        }
        
        
        if(rs!=null){
            rs.close();
        }
        if(pstmt!=null){
            pstmt.close();
        }
        if(connection!=null){
            connection.close();
        }
        
    }
}

三,,批處理執(zhí)行

有時(shí)候需要向數(shù)據(jù)庫(kù)發(fā)送一批SQL語句執(zhí)行,這時(shí)應(yīng)避免向數(shù)據(jù)庫(kù)一條條的發(fā)送執(zhí)行,,而應(yīng)采用JDBC的批處理機(jī)制,,以提升執(zhí)行效率。

無論使用Statement對(duì)象還是使用PreparedStatement對(duì)象都可以實(shí)現(xiàn)

這里介紹使用PreparedStatement來實(shí)現(xiàn)的方式

  1. 獲取PreparedStatement對(duì)象
  2. 設(shè)置每條批處理的參數(shù)
  3. 將一組參數(shù)添加到批處理命令中

下面上實(shí)例代碼

public class Demo1 {
    private String user="root";
    private String password="root";
    private String url="jdbc:mysql://localhost:3306/mydb";
    
    
    @Test
    public void test1() throws Exception{
        List<User> list = new ArrayList<User>();
        for(int i = 0;i < 10;i  ){
            User user = new User();
            user.setUsername("albee" i);
            user.setPwd("123456");
            list.add(user);
        }
        
        sava(list);
        
        
    }
    
    public void sava(List<User> l) throws Exception{
        Class.forName("com.mysql.jdbc.Driver");
        
        Connection connection = DriverManager.getConnection(url, user, password);
        String sql = "insert into user(username,pwd) values(?,?)";
        PreparedStatement pstmt = connection.prepareStatement(sql);
        
        for(int i = 0;i<l.size();i  ){
            pstmt.setString(1, l.get(i).getUsername());
            pstmt.setString(2, l.get(i).getPwd());
            
            pstmt.addBatch();
            
            // 每到五條就執(zhí)行一次對(duì)象集合中的批處理命令,,
            if(i%5==0){        
                pstmt.executeBatch();
                pstmt.clearBatch();
            }   
        }
        // 不足五條也要執(zhí)行一次
        pstmt.executeBatch();
        pstmt.clearBatch();
        
        if(pstmt!=null){
            pstmt.close();
        }
        if(connection!=null){
            connection.close();
        }
    }
}

四,,事務(wù)的操作

有時(shí)候我們需要完成一組數(shù)據(jù)庫(kù)操作,這其中的操作有一個(gè)失敗則整個(gè)操作就回滾,,即組成事務(wù)的每一個(gè)操作都執(zhí)行成功整個(gè)事務(wù)才算成功執(zhí)行

常見的例子就是銀行轉(zhuǎn)帳業(yè)務(wù)

update account set money=money-1000 where accountName='張三';

update account set money=money 1000 where accountName='李四';

已經(jīng)在mydb中創(chuàng)建了account表,,包含accountName和money字段,并插入了兩條記錄

實(shí)例代碼:

// 使用事務(wù)
    @Test
    public void test2(){
        String url = "jdbc:mysql://localhost:3306/mydb";
        String user = "root";
        String password = "root";
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(url,user,password);
            connection.setAutoCommit(false);  //設(shè)置事務(wù)為手動(dòng)提交  
            String sql_zs = "update account set money=money-1000 where accountName='張三'";
            String sql_ls = "update account set money=money 1000 where accountName='李四'";
            
            pstmt = connection.prepareStatement(sql_ls);
            int count_ls = pstmt.executeUpdate();

            pstmt = connection.prepareStatement(sql_zs);
            int count_zs = pstmt.executeUpdate();

            
        }catch (Exception e) {
            e.printStackTrace();
            try {
                connection.rollback();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        } finally {
            try {
                connection.commit();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            if(pstmt!=null){
                try {
                    pstmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(connection!=null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

如果事務(wù)執(zhí)行成功

執(zhí)行前和執(zhí)行后表的變動(dòng)

來源:https://www./content-4-542801.html

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多