J2EE梳理(六)——關於JDBC的基礎


來源於how2j

建立連接

導入Mysql-jdbc的jar包

初始化驅動

  • 通過Class.forName(“com.mysql.jdbc.Driver”);
  • 初始化驅動類com.mysql.jdbc.Driver;就在 mysql-connector-java-5.0.8-bin.jar中
  • 如果忘記了第一個步驟的導包,就會拋出ClassNotFoundException
  • Class.forName是把這個類加載到JVM中,加載的時候,就會執行其中的靜態初始化塊,完成驅動的初始化的相關工作。
  • 代碼:
package jdbc;
   
public class TestJDBC {
    public static void main(String[] args) {
           
        //初始化驅動
        try {
            //驅動類com.mysql.jdbc.Driver
            //就在 mysql-connector-java-5.0.8-bin.jar中
            //如果忘記了第一個步驟的導包,就會拋出ClassNotFoundException
            Class.forName("com.mysql.jdbc.Driver");
              
            System.out.println("數據庫驅動加載成功 !");
   
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
           
    }
}
  • res:在這裏插入圖片描述

建立與數據庫的連接

  • 建立與數據庫的Connection連接
  • 這裏需要提供:
數據庫所處於的ip:127.0.0.1 (本機)
數據庫的端口號: 3306 (mysql專用端口號)
數據庫名稱 how2java
編碼方式 UTF-8
賬號 root
密碼 admin
  • 代碼:
package jdbc;
  
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
  
public class TestJDBC {
    public static void main(String[] args) {
  
        try {
            Class.forName("com.mysql.jdbc.Driver");
  
            // 建立與數據庫的Connection連接
            // 這裏需要提供:
            // 數據庫所處於的ip:127.0.0.1 (本機)
            // 數據庫的端口號: 3306 (mysql專用端口號)
            // 數據庫名稱 how2java
            // 編碼方式 UTF-8
            // 賬號 root
            // 密碼 admin
  
            Connection c = DriverManager
                    .getConnection(
                            "jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
                            "root", "admin");
  
            System.out.println("連接成功,獲取連接對象: " + c);
  
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
  
    }
}
  • res:在這裏插入圖片描述

創建Statement

  • Statement是用於執行SQL語句的,比如增加,刪除
  • 代碼:
package jdbc;
  
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
  
public class TestJDBC {
    public static void main(String[] args) {
  
        try {
            Class.forName("com.mysql.jdbc.Driver");
  
            Connection c = DriverManager
                    .getConnection(
                            "jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
                            "root", "admin");
  
            // 注意:使用的是 java.sql.Statement
            // 不要不小心使用到: com.mysql.jdbc.Statement;
            Statement s = c.createStatement();
  
            System.out.println("獲取 Statement對象: " + s);
  
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
  
    }
}
  • res:在這裏插入圖片描述

執行SQL語句

-s.execute執行sql語句;執行成功後,用mysql-front進行查看,明確插入成功

  • 代碼:
package jdbc;
  
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
  
public class TestJDBC {
    public static void main(String[] args) {
  
        try {
            Class.forName("com.mysql.jdbc.Driver");
  
            Connection c = DriverManager
                    .getConnection(
                            "jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
                            "root", "admin");
  
            Statement s = c.createStatement();
  
            // 準備sql語句
            // 注意: 字符串要用單引號'
            String sql = "insert into hero values(null,"+"'提莫'"+","+313.0f+","+50+")";
            s.execute(sql);
  
            System.out.println("執行插入語句成功");
  
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
  
    }
}

關閉連接

  • 數據庫的連接是有限資源,相關操作結束後,養成關閉數據庫的好習慣
  • 先關閉Statement
  • 後關閉Connection
package jdbc;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
 
public class TestJDBC {
    public static void main(String[] args) {
 
        Connection c = null;
        Statement s = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
 
            c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8", "root",
                    "admin");
 
            s = c.createStatement();
 
            String sql = "insert into hero values(null," + "'提莫'" + "," + 313.0f + "," + 50 + ")";
 
            s.execute(sql);
 
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            // 數據庫的連接時有限資源,相關操作結束後,養成關閉數據庫的好習慣
            // 先關閉Statement
            if (s != null)
                try {
                    s.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            // 後關閉Connection
            if (c != null)
                try {
                    c.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
 
        }
 
    }
}

JDBC的增刪改

 public static void main(String[] args) {
   
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
   
        try (
            Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
                "root", "admin");
            Statement s = c.createStatement();             
        )
        {
            String sql = "insert into hero values(null," + "'提莫'" + "," + 313.0f + "," + 50 + ")";
            s.execute(sql);
               
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

刪除

public static void main(String[] args) {
   
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
   
        try (
            Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
                "root", "admin");
            Statement s = c.createStatement();             
        )
        {
            String sql = "delete from hero where id = 5";
            s.execute(sql);
               
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

修改

public static void main(String[] args) {
   
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
   
        try (
            Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
                "root", "admin");
            Statement s = c.createStatement();             
        )
        {
            String sql = "update hero set name = 'name 5' where id = 3";
            s.execute(sql);
               
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

通用方法

  • 設計一個方法:public static void execute(String sql):方法接受的參數是SQL語句,無論是增加,刪除,還是修改,都調用這個方法,每次傳不同的SQL語句作爲參數
  • 代碼:
public static void execule(String sql)
{
    Connection c = null;
    Statement s = null; 
    try
    {
	    Class.forName("com.mysql.jdbc.Driver");
	     
	    c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root","admin");
	    s = c.createStatement();
	     
	    s.execute(sql);
	     
	    System.out.println("操作成功!");
    }
    catch (ClassNotFoundException e)
    {
        e.printStackTrace();
    }
    catch (SQLException e)
    {
        e.printStackTrace();
    }
    finally
    {
        if(s != null)
        {
            try
            {
            s.close();
            }
            catch(SQLException e)
            {
                e.printStackTrace();
            }
        }
        if(c != null)
        {
            try
            {
            c.close();
            }
            catch(SQLException e)
            {
                e.printStackTrace();
            }
        }
    }
     
}

查詢

利用ResultSet接收返回值

  • 代碼:
package jdbc;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
 
public class TestJDBC {
    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
 
        try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
                "root", "admin"); Statement s = c.createStatement();) {
 
            String sql = "select * from hero";
 
            // 執行查詢語句,並把結果集返回給ResultSet
            ResultSet rs = s.executeQuery(sql);
            while (rs.next()) {
                int id = rs.getInt("id");// 可以使用字段名
                String name = rs.getString(2);// 也可以使用字段的順序
                float hp = rs.getFloat("hp");
                int damage = rs.getInt(4);
                System.out.printf("%d\t%s\t%f\t%d%n", id, name, hp, damage);
            }
            // 不一定要在這裏關閉ReultSet,因爲Statement關閉的時候,會自動關閉ResultSet
            // rs.close();
 
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
  • res:在這裏插入圖片描述

SQL語句判斷賬號密碼是否正確

  • 判斷賬號密碼的正確方式是根據賬號和密碼到表中去找數據,如果有數據,就表明密碼正確了,如果沒數據,就表明密碼錯誤。

  • 不恰當的方式 是把uers表的數據全部查到內存中,挨個進行比較。 如果users表裏有100萬條數據呢? 內存都不夠用的。

  • 代碼:

try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
                "root", "admin");
                Statement s = c.createStatement();
                 
                ) {
            String name = "dashen";
            //正確的密碼是:thisispassword
            String password = "thisispassword1";
   
            String sql = "select * from user where name = '" + name +"' and password = '" + password+"'";
              
            // 執行查詢語句,並把結果集返回給ResultSet
            ResultSet rs = s.executeQuery(sql);
              
            if(rs.next())
                System.out.println("賬號密碼正確");
            else
                System.out.println("賬號密碼錯誤");
             
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
  • 即sql找到了結果 ResultSet裏纔有next對象
  • res:在這裏插入圖片描述

找到總數

  • 設計一個方法,進行分頁查詢:public static void list(int start, int count):start 表示開始頁數,count表示一頁顯示的總數;list(0,5) 表示第一頁,一共顯示5條數據;list(10,5) 表示第三頁,一共顯示5條數據
  • 代碼:
String sql = "select count(*) from hero";
 
            ResultSet rs = s.executeQuery(sql);
            int total = 0;
            while (rs.next()) {
                total = rs.getInt(1);//字段順序
            }

分頁查詢

  • 代碼:
package jdbc;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
 
public class TestJDBC {
    public static void main(String[] args) {
        list(0, 5); 
        System.out.println();
        list(5, 10); 
    }
     
    public static void list(int start, int count) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            // TODO 自動生成的 catch 塊
            e.printStackTrace();
        }
        Connection c = null;
        try {
            c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8"
                    ,"root","admin");
            Statement s = c.createStatement();
             
            String str = "select * from hero limit "+start+","+count;
             
            ResultSet rs = s.executeQuery(str);
             
            while(rs.next()) {
                int id = rs.getInt(1);
                String name = rs.getString(2);
                float hp = rs.getFloat(3);
                int damage = rs.getInt(4);
                System.out.printf("%d \t %s \t %f \t %d %n",id,name,hp,damage);
                 
            }
        } catch (SQLException e) {
            // TODO 自動生成的 catch 塊
            e.printStackTrace();
        }
    }
     
}
  • res:在這裏插入圖片描述

PreparedStatement

PreparedStatement的使用

  • 和 Statement一樣,PreparedStatement也是用來執行sql語句的
  • 與創建Statement不同的是,需要根據sql語句創建PreparedStatement
  • 除此之外,還能夠通過設置參數,指定相應的值,而不是Statement那樣使用字符串拼接
  • 代碼:
package jdbc;
    
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
    
public class TestJDBC {
    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
  
        String sql = "insert into hero values(null,?,?,?)";
        try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
            // 根據sql語句創建PreparedStatement
            PreparedStatement ps = c.prepareStatement(sql);
        ) {
             
            // 設置參數
            ps.setString(1, "提莫");
            ps.setFloat(2, 313.0f);
            ps.setInt(3, 50);
            // 執行
            ps.execute();
  
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
    }
}
  • res:在這裏插入圖片描述

PreparedStatement的優點

  • Statement 需要進行字符串拼接,可讀性和維護性比較差
    String sql = "insert into hero values(null,"+"'提莫'"+","+313.0f+","+50+")";
  • PreparedStatement 使用參數設置,可讀性好,不易犯錯String sql = "insert into hero values(null,?,?,?)";
			String sql = "insert into hero values(null,?,?,?)";
			PreparedStatement ps = c.prepareStatement(sql);
			// PreparedStatement 使用參數設置,可讀性好,不易犯錯
            // "insert into hero values(null,?,?,?)";
            ps.setString(1, "提莫");
            ps.setFloat(2, 313.0f);
            ps.setInt(3, 50);
            ps.execute();
  • PreparedStatement有預編譯機制,性能比Statement更快
			// PreparedStatement 執行10次,只需要1次把SQL語句傳輸到數據庫端
            // 數據庫對帶?的SQL進行預編譯
  
            // 每次執行,只需要傳輸參數到數據庫端
            // 1. 網絡傳輸量比Statement更小
            // 2. 數據庫不需要再進行編譯,響應更快
  • PreparedStatement的優點3-防止SQL注入式攻擊:
  • 代碼:
public static void main(String[] args) {
  
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
  
        String sql = "select * from hero where name = ?";
        try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
                Statement s = c.createStatement();
            PreparedStatement ps = c.prepareStatement(sql);
        ) {
            // 假設name是用戶提交來的數據,可以自己編輯,如果惡意編輯爲以下
            String name = "'蓋倫' OR 1=1";
            String sql0 = "select * from hero where name = " + name;
            // 拼接出來的SQL語句就是
            // select * from hero where name = '蓋倫' OR 1=1
            // 因爲有OR 1=1,所以恆成立
            // 那麼就會把所有的英雄都查出來,而不只是蓋倫
            // 如果Hero表裏的數據是海量的,比如幾百萬條,把這個表裏的數據全部查出來
            // 會讓數據庫負載變高,CPU100%,內存消耗光,響應變得極其緩慢
            System.out.println(sql0);
  
            ResultSet rs0 = s.executeQuery(sql0);
            while (rs0.next()) {
                String heroName = rs0.getString("name");
                System.out.println(heroName);
            }
  
            s.execute(sql0);
  
            // 使用預編譯Statement就可以杜絕SQL注入
  
            ps.setString(1, name);
  
            ResultSet rs = ps.executeQuery();
            // 查不出數據出來
            while (rs.next()) {
                String heroName = rs.getString("name");
                System.out.println(heroName);
            }
 
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
  
    }

execute與executeUpdate

  • execute與executeUpdate的相同點:都可以執行增加,刪除,修改
  • 不同1:execute可以執行查詢語句,然後通過getResultSet,把結果集取出來;executeUpdate不能執行查詢語句
  • 不同2:execute返回boolean類型,true表示執行的是查詢語句,false表示執行的是insert,delete,update等等
    executeUpdate返回的是int,表示有多少條數據受到了影響
發佈了117 篇原創文章 · 獲贊 59 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章