JDBC

1.1 JDBC概念和本質

JDBC是sun公司提供的一套操作關係型數據庫的規範(接口),這些接口由各個數據庫生產商實現。數據庫生產商將接口的實現類會打成一個開發包,這個開發包就是jar包。我們要使用哪個數據庫將哪個數據庫廠商提供的jar導入程序就行了。
在這裏插入圖片描述

1.2 JDBC入門程序

public class JdbcDemo1 {
  public static void main(String[] args) throws Exception {
    //1. 導入驅動jar包
    //2.註冊驅動
    Class.forName("com.mysql.jdbc.Driver");
    //3.獲取數據庫連接對象  假設獲取連接的時候要Driver對象
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "root");
    //4.定義sql語句
    String sql = "update account set balance = 500 where id=1";
    //5.獲取執行sql的對象 Statement
    Statement stmt = conn.createStatement();
    //6.執行sql
    int count = stmt.executeUpdate(sql);
    //7.處理結果
    System.out.println(count);
    //8.釋放資源
    stmt.close();
    conn.close();
  }
}

jar 的導入: 在項目的根目錄下新建一個lib目錄,把mysql-connector-java-5.1.37-bin.jar放進去

2.JDBC中API

2.1 com.sql.DriverManager作用

1、註冊驅動:DriverManager.registerDriver(new Driver()),但是我們不使用,在開發中使用Class.forName("com.mysql.jdbc.Driver"),因爲使用DriverManager的registerDriver註冊驅動會註冊兩次。

2、獲取連接:
	static Connection getConnection(String url, String user, String password);
	String url:連接數據庫的路徑
		語法:jdbc:mysql://localhost:3306/數據庫名稱
				如果是本機的數據庫,可以簡寫:jdbc:mysql:///數據庫名稱
	String user:用戶名
	String password:密碼

2.2 com.sql.Connetion作用

1、獲取執行sql語句的對象
	Statement createStatement();
	PreparedStatement preparedStatement(String sql);
2、事務管理(下面專題6講解)

2.3 com.sql.Statement作用

作用:執行sql語句
1. boolean execute(String sql) :可以執行任意的sql 瞭解,如果執行的是查詢語句,就返回
2. true,如果執行的是DML或者DDL語句,那麼就返回false3. int executeUpdate(String sql) :執行DML(insert、update、delete)語句、
DDL(create,alter、drop)語句
		* 返回值:影響的行數,可以通過這個影響的行數判斷DML語句是否執行成功 返回值>0的
		則執行成功,反之,則失敗。
5. ResultSet executeQuery(String sql)  :執行DQL(select)語句

2.4 com.sql.ResultSet作用

在這裏插入圖片描述

1、判斷是否有下一條數據
2、獲取當前行數據
while (rs.next()){
   //獲取id
   int id = rs.getInt("id");
   //獲取name
   String name = rs.getString("name");
   //獲取balance
   double balance = rs.getDouble("balance");
   //打印結果
   System.out.println(id+","+name+","+balance);
}

注意:如果該列的數據類型是int類型,也可以使用getString(“列名”)來獲取,但是反過來就不行。getInt(1)表示獲取第一列的值,而getInt(“1”)表示獲取列名爲1的這一列的值,二者有區別。

3.使用Statement對象執行增、刪、改、查操作

3.1 執行增、刪、改的步驟

1、註冊驅動:Class.forName("com.mysql.jdbc.Driver");
2、獲取鏈接:DriverManager.getConnection("jdbc:mysql://localhost:3306/數據庫名","root","root");
3、獲取執行sql的Statement對象:stmt = conn.createStatement();
4、執行sql語句,獲取結果
5、處理結果
6、釋放資源

3.2 執行查詢的步驟

1、註冊驅動:Class.forName("com.mysql.jdbc.Driver");
2、獲取鏈接:DriverManager.getConnection("jdbc:mysql://localhost:3306/數據庫名","root","root");
3、獲取執行sql的Statement對象:stmt = conn.createStatement();
4、執行sql語句,獲取結果集
5、遍歷結果集獲取數據
6、釋放資源

4.JDBCUtils工具類

  • 目標和分析
/*
    將jdbc操作重複的代碼封裝到此工具類中
    封裝如下操作:
        加載配置文件 只需要加載一次就行了,放到靜態代碼塊中
        註冊驅動:Class.forName("com.mysql.jdbc.Driver");  只需要註冊一次就行了,放到靜態代碼塊中
        獲取連接:conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3","root","root");
        釋放資源
    目的:簡化jdbc代碼的數據
 */
  • 在JDBCUtils工具類的靜態代碼塊中讀取配置文件和註冊驅動(核心代碼)
static {
  try {
    //加載配置文件
    //1 創建Properties 對象
    Properties properties=new Properties();
    //2 調用load方法加載配置文件
    //使用類加載器獲取src路徑中文件的輸入流對象
    //ClassLoader loader = JDBCUtils.class.getClassLoader();
    //獲取流
    InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
    properties.load(is);
    //3 調用getProperty方法根據key獲取value值
    String driver = properties.getProperty("driver");
    url=properties.getProperty("url");
    user=properties.getProperty("user");
    password=properties.getProperty("password");

    // 註冊驅動
    Class.forName(driver);
  } catch (ClassNotFoundException e) {
    e.printStackTrace();
  } catch (IOException e) {
    e.printStackTrace();
  }
}
  • 在JDBCUtils工具類中對外提供獲取連接和釋放資源的方法
//對外提供一個獲取連接的方法
public static Connection getConnection() throws SQLException {
  return DriverManager.getConnection(url,user,password);
}
//對外提供一個釋放資源的方法
public static void close(Statement stmt,Connection conn){
  close(null,stmt,conn);
}
//重載
public static void close(ResultSet rs, Statement stmt,Connection conn){
  if(rs!=null){
    try {
      rs.close();
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }
  if(stmt!=null){
    try {
      stmt.close();
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }
  if (conn!=null) {
    try {
      conn.close();
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }
}

5.使用PreparedStatement對象執行增、刪、改、查操作

5.1 sql注入漏洞的原因和解決辦法

原因:在使用Statement對象執行sql語句時,如果sql語句中拼接的變量包含sql關鍵字,那麼就可能會出現sql注入漏洞。
解決:不使用Statement對象,使用PreparedStatement對象執行sql。

PreparedStatement相比Statement的優點

1、不會產生sql注入漏洞問題
2、效率高

5.2 PreparedStatement對象執行增、刪、改

1、通過工具類獲取連接
2、獲取PreparedStatement對象,預編譯sql語句
3、如果sql語句中有?佔位符,那麼就設置參數
4、執行增刪改,獲取影響的行數,int count=pstmt.executeUpdate();
5、處理結果
6、釋放資源
public class InsertTest {
  public static void main(String[] args) {
    Connection conn = null;
    PreparedStatement pstmt = null;
    try {
      //1 通過工具類獲取連接
      conn = JdbcUtils.getConnection();
      //2 獲取PreparedStatement對象,預編譯sql語句
      pstmt = conn.prepareStatement("insert into account values(null,?,?)");
      //3 如果sql語句中有?,那麼就設置參數
      pstmt.setString(1,"小迷妹");
      pstmt.setDouble(2,0.5);
      //4 執行sql,獲取結果
      int count = pstmt.executeUpdate();
      //5 處理結果
      System.out.println(count>0?"添加成功":"添加失敗");
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      //6 釋放資源
      JdbcUtils.close(pstmt,conn);
    }
  }
}

5.3 PreparedStatement對象執行查詢

1、通過工具類獲取連接
2、獲取PreparedStatement對象,預編譯sql語句
3、如果sql語句中有?佔位符,那麼就設置參數
4、執行查詢操作,獲取結果集對象;ResultSet rs = pstmt.executeQuery();
5、遍歷結果集,獲取數據
6、釋放資源
//定義一個登錄的方法
public static boolean login(String name,String password){
  Connection conn = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
  try {
    //1 通過工具類獲取連接
    conn = JdbcUtils.getConnection();
    //2 獲取PreparedStatement對象,預編譯sql語句
    pstmt = conn.prepareStatement("select * from user where name=? and password=?");
    //3 如果有?佔位符就設置參數
    pstmt.setString(1,name);
    pstmt.setString(2,password);
    //4 執行sql 獲取結果
    rs = pstmt.executeQuery();
    //5 處理結果,返回結果
    return rs.next();
  } catch (SQLException e) {
    e.printStackTrace();
  } finally {
    //6 釋放資源,
    JdbcUtils.close(rs,pstmt,conn);
  }
  return false;
}

6.jdbc事務管理

1 事務管理的概念

一組sql操作要麼同時成功要麼同時失敗,那麼就需要統一管理,這就是事務管理。

6.2 事務管理API

獲取到連接對象之後開啓事務:conn.setAutoCommit(false);
一組sql執行完成之後提交事務:conn.commit();catch中回滾事務:conn.rollback();

注意:在執行事務管理的時候,一般是捕獲一個最大的Exception異常,出現任何異常都要回滾。

6.3 代碼示例

public class TransactionTest {
  public static void main(String[] args) {
    Connection conn = null;
    PreparedStatement pstmt = null;
    try {
      //1 通過工具類獲取連接
      conn = JdbcUtils.getConnection();
      //開啓事務-------------------------------
      conn.setAutoCommit(false);
      //2 獲取PreparedStatement對象,預編譯sql語句
      pstmt = conn.prepareStatement("update account set balance=balance+? where name=?");
      //1、張三的賬戶-500
      //3 如果有?,就設置參數
      pstmt.setDouble(1,-500);
      pstmt.setString(2,"張三");
      //4 執行sql
      pstmt.executeUpdate();

      //製造異常
      //int i=10/0;

      //2、楊鋅怒的賬戶+500
      //3 如果有?,就設置參數
      pstmt.setDouble(1,500);
      pstmt.setString(2,"楊鋅怒");
      //4 執行sql
      pstmt.executeUpdate();

      //提交事務-------------------------------
      conn.commit();

    } catch (Exception e) {
      //            e.printStackTrace();
      System.out.println("事務回滾了");
      //回滾事務---------------------------------
      if (conn!=null) {
        try {
          conn.rollback();
        } catch (SQLException e1) {
          e1.printStackTrace();
        }
      }
    } finally {
      //6 釋放資源
      JdbcUtils.close(pstmt,conn);
    }
  }
}

總結

1、JDBCUtils工具類封裝 註冊驅動、獲取連接、釋放資源
	private static String url;
    private static String user;
    private static String password;
    static {
        //1 加載配置文件  只需要加載一次
        //1.1 創建Properties對象
        Properties properties=new Properties();
        //1.2 調用load方法加載配置文件
        InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
        try {
            properties.load(is);
            //1.3 調用getProperty方法,根據key獲取value值
            String driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            user = properties.getProperty("user");
            password = properties.getProperty("password");
        //2 註冊驅動 只需要註冊一次  可以放到靜態代碼塊中
        Class.forName(driver);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
2、使用PreparedStatement對象執行增刪改查的思路
	增刪改的思路:
		1、通過工具類獲取連接
		2、獲取PreparedStatement對象,預編譯sql語句
		3、如果sql語句中有?佔位符,那麼就設置參數
		4、執行增刪改,獲取影響的行數,int count=pstmt.executeUpdate();
		5、處理結果
		6、釋放資源
	查詢的思路:
		1、通過工具類獲取連接
		2、獲取PreparedStatement對象,預編譯sql語句
		3、如果sql語句中有?佔位符,那麼就設置參數
		4、執行查詢操作,獲取結果集對象;ResultSet rs = pstmt.executeQuery();
		5、遍歷結果集,獲取數據
		6、釋放資源
3、使用JDBC完成事務管理
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章