MySql數據庫基礎知識(一)

JDBC數據庫的連接

  • 概述

    • JDBC(Java DataBase Connectivity,java數據庫連接)是一種用於執行SQL語句的Java API
  • 核心組件

    • DriverManager–此類管理數據庫驅動程序列表

      • 這一類可以不寫或使用映射方式Class.forName()
      • 使用通信子協議將來自java應用程序的連接請求與適當的數據庫驅動程序匹配。
    • Driver --此接口處理與數據庫服務器的通信

    • Connection --用於聯繫數據庫的所有方法

    • Statement – 使用從此接口創建的對象將SQL語句提交到數據庫

      • 增,刪,改 executeUpdate==>int
      • 查 executeQuery()==>result
      • execute==>true-Result(查詢的結果)/false- int (增刪改)
      String sql="select * from tb_name where  name='"+uname+"'"      "
      Statement stmt=conn.createConnection(sql);
      ResultSet=stmt.executeQuery();
      /*
      *    有SQL注入問題  ---- ' or '3'='3;     ' or '1'='1		
      *	預防SQL注入問題--PreparedStatement
      */
      
    • PreparedStatement

      • Statement 的升級版

      • String sql="select * from tb_name where name = ?";
        PreparedStatement ptmt= conn.preparedStatement(sql);
        ptmt.setString(1,name);//和Result查詢第一列一致,默認第一個爲1
        ResultSet=ptmt.executeQuery();
        
    • ResultSet–查詢結果集

    • 在使用Statement對象執行SQL查詢後,這些對象保存從數據庫檢索的數據。它作爲一個迭代器,允許我們移動其數據。

      • 表示數據庫結果集的數據表,通常通過執行查詢數據庫的語句生成。

      • ResultSet 對象具有指向其當前數據行的光標。最初,光標被置於第一行之前。

      • next 方法將光標移動到下一行;因爲該方法在 ResultSet 對象沒有下一行時返回 false

      • 所以可以在 while循環中使用它來迭代結果集。

      • 默認的 ResultSet 對象不可更新,僅有一個向前移動的光標。因此,只能迭代它一次,並且只能按從第一行到最後一行的順序進行

    • SQLException --此類處理數據庫應用程序中發生的任何錯誤

  • 數據庫連接標程

import java.sql.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Demo01{
    public static void main(String[] args) throws SQLException,ClassNotFindException {
        //1、獲取驅動
        Class.forName("com.mysql.jdbc.Driver");
        //2 創建連接
        Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/api_db?user=root&password=123456");
        //3獲取執行sql語句對象
        Statement stmt=conn.createStatement();
        //4編寫SQL語句
        String sql="select * from a_doc";
        //5運行SQL語句並返回結果集
        ResultSet result=stmt.executeQuery(sql);
        //6解析結果
        //while(result.next()){
        System.out.println(result);
        //}
        //7關閉
        result.close();
        stmt.close();
        conn.close();
    }
}

補充

  • 步驟2 -多種寫法
Thread.currentThread().getContextClassLoader().getResourceAsStream("");
properties.load(new FileInputStream("db.properties"));

Connection conn = 
DriverManager.getConnection("jdbc:mysql://localhost:3306/table?user=root&password=root");
DriverManager.getConnection("jdbc:mysql://localhost:3306/java1908", "root", "root");
----------------------------------------
//第三種 --直接賦值
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "root");
Connection conn = 
DriverManager.getConnection("jdbc:mysql://localhost:3306/java1908?useSSL=false", info);
-------------------------------------------
//第四種-- 調用文件    
Properties propertieds = new Properties();

propertieds.load(new FileInputStream("db.properties"));
/*如上述語句失效,
	FileInputStream in=Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties");
	properties.load(in);
*/		
String user = propertieds.getProperty("user");
String url = propertieds.getProperty("url");
String password = propertieds.getProperty("password");
		
Connection conn = DriverManager.getConnection(url, user,password);

事務

  • 定義
    • 事務(Transaction),一般是指要做的或所做的事情。在計算機[術語]中是指訪問並可能更新數據庫中各種[數據項]的一個程序執行單元(unit)
    • 對數據庫而已,一個SQL語句就是一個事務
  • 意義
    • 保證數據的完整性和一致性

事務的四大特性–(原子,一致,持久,隔離)

  • 1、原子性
    • 事務是一個最小的操作單元,不可再被分割,即事務中的sql語句要麼同時生效,要麼同時不生效。
  • 2、一致性
    • 事務中的數據在事務提交之前,或者回滾以後,是一致的。
  • 3、持久性
    • 事務一旦提交,對數據的影響是持久的(寫入到磁盤中)。
  • 4、隔離性
    • 一個事務,在併發訪問的情況下,不同隔離級別會出現不同效果。

事務的隔離級別***

  • 一個事務,在併發訪問的情況下,不同隔離級別會出現不同效果。

  • 併發: 在同一時刻,有多個客戶在操作同一張表。同一時刻發生(前提條件)

    • 並行:在一定的時間段內運行
  • 1.read uncommitted

    • 一個事務中讀到了另一個事務並未提交的結果。
    • A 轉賬但未提交,B取讀到A提交後的結果,但數據可能有誤(A中途回滾,結果也會改變)
    • 這種隔離級別就會導致: 髒讀、不可重複讀、虛讀(幻讀)。
  • 2.read committed——oracle的默認隔離級別–

    • 一個事務中能讀到另一個事務已經提交的結果,但是不能讀到另一個事務沒有提交的結果。
    • A給B轉賬,只有A提交後B才能讀到更新的數據,否則不論A如何操作,查詢的結果都是原始數據
  • 這種隔離級別解決了髒讀問題。但出現了不可重複讀和幻讀的問題,

    • 所謂不可重複讀,就是不能重複讀,一重複讀數據就不一樣。
    • 所謂的幻讀,在一個事務中,兩次讀到的數據的條數不相同。
    • 髒讀:讀取未提交數據
    • 不可重複讀:前後多次讀取,數據內容不一致
    • 幻讀:前後多次讀取,數據總量不一致

    3.repeatable read——mysql的默認隔離級別

    • 一個事務中可以重複的讀,每次讀到的數據都是一樣的
    • 在並行的過程中,只要一開啓事務,只要事務不結束,讀取的值始終是一致的
    • 無論其他事務對數據進行怎樣的操作(添加數據、修改數據、提交事務)。當前事務每次讀到的數據內容都不會有變化。
    • 這種隔離級別解決了: 髒讀、不可重複讀、幻讀。
  • 4.serializable 串行化–排隊執行

    • 最嚴苛的隔離級別。將並行變成串行。效率非常低,沒有使用場景。
  • 注:

    • repeatable read 和read committed隔離本質一樣
    • 讀到的數據=事務沒有開始之前的數據,當事務提交話,讀到的數據=遞交後的數據
  • 查看和設置隔離級別

    • 查看當前數據庫事務隔離級別
      • select @@tx_isolation;
    • 設置隔離級別
      • set session transaction isolation level read uncommitted;
      • set session transaction isolation level read committed;
      • set session transaction isolation level repeatable read;
      • set session transaction isolation level serializable;

使用方式

  • 1、設置隔離級別
  • 2、開啓事務
  • 3、提交事務

事務的開啓

  • 數據庫中
    • start transaction
  • java 中
    • conn.setAutoCommit(false)

事務的結束

  • 提交 :commit();//conn.commit();
  • 回滾:rollback();//conn.rollback();

補充-擴展_設置事務的回滾點

  • 設置事務的回滾點

    • Savepoint point = conn.setSavepoint();
  • 回滾到具體位置

    • conn.rollback(point);
package com.qianfeng.demos;

import java.io.IOException;
import java.sql.Connection;
import java.sql.Savepoint;
import java.sql.Statement;

import com.qianfeng.utils.JDBCUtil;

public class Demo14 {

	public static void main(String[] args) throws IOException, Exception {
		// 獲取連接對象
		Connection conn = JDBCUtil.getConnection();
		// 創建statment對象
		String sql01 = "update account set money=money-1000 where name='zhangsan'";
		String sql02 = "update account set money=money+1000 where name='lisi'";
		
//		PreparedStatement pstmt01 = conn.prepareStatement(sql01);
//		PreparedStatement pstmt02 = conn.prepareStatement(sql02);
		
		Statement stmt = conn.createStatement();
		
		conn.setAutoCommit(false);
		Savepoint point = null;
		
		try {
			int ret01 = stmt.executeUpdate(sql01);
			System.out.println("張三轉出成功....");
			
			point = conn.setSavepoint();
			System.out.println("已經保存當前狀態...");
			
			int i = 10/0;
			
			int ret02 = stmt.executeUpdate(sql02);
			System.out.println("李四接收成功");
			
			// 如果代碼能執行到這兒,說明沒有問題,可以提交
			conn.commit();
		}catch (Exception e) {
			// 如果代碼執行到這裏,說明遇到了異常,回滾到zhangsan轉出的狀態
			conn.rollback(point);
			System.err.println("已經回滾到張三轉出的狀態,繼續向lisi轉賬... ...");
			
			int ret02 = stmt.executeUpdate(sql02);
			conn.commit();
			System.out.println("再次嘗試向李四轉賬成功... ");
		}
		JDBCUtil.releaseSource(stmt, conn);
		
	}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章