原生的JDBC

1、JDBC連接數據的步驟

  1. 加載驅動
  2. 根據URL、用戶名和密碼建立連接
  3. 創建處理快,有靜態處理快(Statement)和預處理塊(PreparedStatement)
  4. 執行數據庫語句
  5. 處理得到的結果
  6. 釋放資源

2、連接

2.1、準備工作

  1. 導入驅動包
    在這裏插入圖片描述

  2. 構建路徑 build path

  3. 測試用戶是否正確登錄

2.2、建立連接

  1. 連接字符串
    1. 加載驅動: oracle.jdbc.driver.OracleDriver
    2. URL:jdbc:oracle:thin:@db 服務器地址:端口:實例
    3. 連接URL:jdbc:oracle:thin:@localhost:1521:orcl
    4. 用戶名和密碼:SCOTT TIGER
  2. 編寫測試類
    1. 加載驅動
    2. 建立連接:Connection con =DriverManager.getConnection(“jdbc:oracle:thin:@locahost:1521:orcl”,“scott”,“tiger”)

3、處理塊

3.1、靜態處理塊

​ Statement 是 Java 執行數據庫操作的一個重要接口,用於在已經建立數據庫連接的基礎上,向數據庫發送要執行的 SQL 語句。Statement 對象,用於執行不帶參數的簡單 SQL 語句。 執行靜態 SQL 語句並返回它所生成結果的對象。

特點:

  • 處理 不變的靜態的 sql 語句
  • 優點: 直接查看sql ,方便處理錯誤
  • 缺點:性能不高、拼接 sql 麻煩、可能存在 sql 注入

方法的使用:

  • 增刪改使用executeUpdate( )函數,返回一個int值,表示影響的行數。
  • 查詢使用executeQurey()函數,返回一個ResultSet對象,該對象中封裝着查詢的信息
    • ResultSet對象必須先試用.next()函數判斷是否有值,才能使用getInt/getString/getBoolean等方法獲取到值(可以簡單的使用getObject()方法獲取到任意類型的數據),如果不使用.next()函數判斷是否有值就直接獲取值,則會出現java.sql.SQLException: 未調用 ResultSet.next異常。

代碼:

/*
 * JDBC基本流程:
 * 	1.加載驅動 (選擇哪一個數據庫)
 * 	2.獲取連接 (與數據庫連接上)
 * 	3.準備sql
 * 	4.獲取處理塊(打包發送)
 * 	5.接收結果集
 * 	6.處理結果數據
 * 	7.關閉
 */

public class Demo01JDBC {
	
	public static void main(String[] args) throws Exception {
		
		//1.加載驅動 (選擇哪一個數據庫)
		Class.forName("oracle.jdbc.OracleDriver");
	  	//2.獲取連接 (與數據庫連接上)
		Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "SCOTT", "TIGER");
	  	//3.準備sql
		String sql = "select * from dept";
	  	//4.獲取處理塊(打包發送)
		Statement sta = conn.createStatement();
	  	//5.接收結果集
		ResultSet result = sta.executeQuery(sql);
	  	//6.處理結果數據
		while(result.next()){
			int deptno = result.getInt("deptno");
			String dname = result.getString("dname");
			String loc = result.getString("loc");
			System.out.println(deptno+"--->:"+dname+"--->"+loc);
		}
	  	//7.關閉資源
		result.close();
		sta.close();
		conn.close();
		
		
	}
}

注意:

  • 釋放資源時,先打開的後關閉。

**優化:**可以將加載數據庫驅動和獲取數據庫連接的操作放在靜態代碼塊中,類只需要加載一次即可,不需要重複加載。

public class Demo02JDBC {
	// 聲明連接數據庫的對象
	public static Connection conn;
	static{
		// 加載數據庫
		try {
			Class.forName("oracle.jdbc.OracleDriver");
			// 和數據庫建立連接
			conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "SCOTT", "TIGER");
			// 準備sql語句
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void main(String[] args)throws Exception {
		// 準備sql語句
		String sql = "select * from dept where deptno=10";
		// 獲取處理塊
		Statement sta = conn.createStatement();
		// 執行sql語句
		ResultSet result = sta.executeQuery(sql);
		// 處理數據
		while(result.next()){
			int deptno = result.getInt(1);
			String dname = result.getString(2);
			String loc = result.getString(3);
			System.out.println(deptno+"--->"+dname+"--->"+loc);
		}
		//7.關閉資源
		result.close();
		sta.close();
		conn.close();
		
	}
}

3.2、預處理塊

​ PreparedStatement 接口繼承了 Statement,並與之在兩方面有所不同:有人主張,在 JDBC 應用中,如果你已經是稍有水平開發者,你就應該始終以PreparedStatement 代替 Statement.也就是說,在任何時候都不要使用 Statement。

由於 PreparedStatement 對象已預編譯過,所以其執行速度要快於 Statement 對象。因此,多次執行的 SQL 語句經常創建爲 PreparedStatement 對象,以提高效率。

特點:

  • 處理 不變的靜態的 sql 語句 |可變的 sql 語句 帶 ? 的 sql
  • 優點:性能高,方便編寫sql 不存在sql注入 安全
  • 缺點:不能直接打印sql語句 不方便處理錯誤

例如要查詢的sql語句爲:select * from users where name=? and pwd=?,要查詢的內容使用?做佔位符。

使用的方法:

  • 設置值:爲sql語句中的?設置值**setInt(字段名|字段的序號)/setString()/setBolean()等設置響應的值,也可以簡單的使用setObject(字段名|字段的序號)**設置任意類型的值。
  • 獲取值:從獲取到的結果集中拿數據,使用函數getInt(字段名|字段的序號)/getSting()/getBoolean(),也可以簡單的使用**getObject(字段名|字段的序號)**獲取任意類型的值。
  • 序號是從1開始的。

代碼:

/**
 * 使用預處理塊查詢數據庫的數據
 *
 */
public class Demo05 {
	
	public static void main(String[] args) throws Exception{
		// 加載數據庫驅動
		Class.forName("oracle.jdbc.OracleDriver");
		// 獲取數據庫的連接
		Connection conn =DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "SCOTT", "TIGER");
		// 準備sql語句(根據用戶名和密碼查詢用戶信息)
		String sql = "select * from users where name=? and pwd=?";
		// 獲取預處理塊,對查詢數據的sql語句進行預編譯
		PreparedStatement ps = conn.prepareStatement(sql);
		// 爲sql語句設置值
		ps.setObject(1, "張萬里");
		ps.setObject(2, "1314");
		// 執行sql語句
		ResultSet result = ps.executeQuery();
		// 處理獲取到的數據
		while(result.next()){
			System.out.println("id"+"\tname"+"\tpwd"+"\tbirthday");
			System.out.println(result.getObject(1)+"\t"+result.getObject(2)+"\t"+result.getObject(3)+"\t"+result.getObject(4));
		}
		
	}

}

3.3、使用db.properties配置文件

db.properties的配置文件

driver=oracle.jdbc.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:xe
uname=SCOTT
pwd=TIGER

使用配置文件獲取數據庫的連接:

/**
 * 數據庫工具類,獲取數據庫的Connection連接對象
 */
public class DBUtil {
	
	// 獲取資源配置文件對象
	private static Properties p = null;
	
	static{
		p = new Properties();
		try {
			// 獲取配置文件
p.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
		} catch (IOException e) {
			System.out.println("加載配置文件失敗");
			e.printStackTrace();
		}
		
		try {
			// 加載數據庫
			Class.forName(p.getProperty("driver"));
		} catch (ClassNotFoundException e) {
			System.out.println("加載數據庫失敗");
			e.printStackTrace();
		}
	}
	
	/**
	 * 獲取數據庫的連接
	 */
	public static Connection getConnection() throws SQLException{
		Connection conn = null;
		conn = DriverManager.getConnection(p.getProperty("url"), p.getProperty("uname"), p.getProperty("pwd"));
		return conn;
	}

3.3.1、模擬註冊賬戶

使用上述的工具類

/**
	 * 註冊
	 */
	public static boolean login(){
		Scanner sc = new Scanner(System.in);
		System.out.print("用戶名:");
		String name = sc.next();
		System.out.print("密碼:");
		String pwd = sc.next();
		Connection conn = null;
		try {
			// 獲取數據庫的連接
			conn = DBUtil.getConnection();
		} catch (SQLException e) {
			System.out.println("連接數據庫失敗");
			e.printStackTrace();
		}
		
		boolean flag = true;
		// 循環檢測要註冊的賬戶是否存在
		while(flag){
			if(check(name, pwd,conn)){
				System.out.println("該用戶已經存在,請重輸入!");
				System.out.print("用戶名:");
				name = sc.next();
				System.out.print("密碼:");
				pwd = sc.next();
			}else{
				flag = false;
			}
		}
		
		// 準備sql語句
		String sql2 = "insert into users values(quecreate_users_id.nextval,?,?)";
		PreparedStatement ps = null;
		// 操作數據庫影響的行數
		int rows = 0;
		try {
			ps = conn.prepareStatement(sql2);
			ps.setObject(1, name);
			ps.setObject(2, pwd);
			// 返回影響的行數
			rows = ps.executeUpdate();
		} catch (SQLException e) {
			System.out.println("向數據庫插入數據異常");
			e.printStackTrace();
		}finally{
			// 關閉資源(自己封裝的方法)
			DBUtil.close(ps, conn);
		}
		
		// 更改標誌位
		if(rows>0){
			System.out.println("註冊成功");
			return true;
		}else{
			System.out.println("註冊失敗");
			return false;
		}
	}

3.3.2、模擬登錄賬戶

/**
	 * 登錄
	 */
	public static void enter(){
		if(user!=null){
			System.out.println("不要重複登錄!");
			start();
			return;
		}
		Scanner sc = new Scanner(System.in);
		System.out.print("用戶名:");
		String name = sc.next();
		System.out.print("密碼:");
		String pwd = sc.next();
		// 連接數據庫
		Connection conn  = null;
		ResultSet result = null;
		PreparedStatement sta = null;
		try {
			conn = DBUtil.getConnection();
			
			boolean flag = true;
			while(flag){
				// 準備sql語句
				String sql = "select * from users where name=? and pwd=?";
				sta = conn.prepareStatement(sql);
				sta.setObject(1, name);
				sta.setObject(2, pwd);
				// 執行sql語句
				result = sta.executeQuery();
				if(result.next()){
					System.out.println("登錄成功");
					flag = false;
				}else{
					System.out.println("用戶名或密碼錯誤,請重新輸入完成登錄");
					System.out.print("用戶名:");
					name = sc.next();
					System.out.print("密碼:");
					pwd = sc.next();
				}
			}
			
		} catch (SQLException e) {
			System.out.println("登錄異常");
			e.printStackTrace();
		}finally {
			DBUtil.close(result, sta, conn);
		}
		user = new User(name,pwd);
		start();
	}

3.3.3、模擬修改密碼

/**
	 * 修改密碼
	 */
	public static void modify(){
		if(user == null){
			System.out.println("登錄後才能修改數據");
			start();
			return;
		}
		Scanner sc = new Scanner(System.in);
		
		// 檢測兩次輸入的密碼
		boolean flag = true;
		String newpwd = null;
		while(flag){
			System.out.print("新密碼:");
			newpwd = sc.next();
			System.out.println("請再次輸入新密碼:");
			String againPwd = sc.next();
			if(!newpwd.equals(againPwd)){
				System.out.println("兩次密碼不一致,請重新輸入");
			}else{
				flag = false;
			}
		}
		
		Connection conn = null;
		PreparedStatement sta = null;
		// 執行sql影響的記錄數
		int rows = 0;
		try {
			// 獲取數據庫的連接
			conn = DBUtil.getConnection();
			// 準備sql語句
			String sql = "update users set pwd=? where name=?";
			sta = conn.prepareStatement(sql);
			sta.setObject(1, newpwd);
			sta.setObject(2, user.getName());
			// 執行sql語句
			rows = sta.executeUpdate();
		} catch (SQLException e) {
			System.out.println("操作數據庫失敗");
			e.printStackTrace();
		}
		
		// 判斷時是否修改成功
		if(rows > 0){
			System.out.println("修改密碼成功!");
			user = null;
			start();
		}
	}

3.3.4、模擬註銷用戶

/**
	 * 註銷用戶
	 */
	public static void delete(){
		if(user == null){
			System.out.println("請先登錄!");
			start();
		}
		Connection conn = null;
		PreparedStatement sta = null;
		// 數據庫操作影響的行
		int rows =0;
		try {
			// 連接數據庫
			conn = DBUtil.getConnection();
			// 準備sql語句
			String sql = "delete from users where name=? and pwd=?";
			sta = conn.prepareStatement(sql);
			// 設置參數
			sta.setObject(1, user.getName());
			sta.setObject(2, user.getPwd());
			// 執行刪除操作
			rows = sta.executeUpdate();
			
		} catch (SQLException e) {
			System.out.println("註銷用戶異常");
			e.printStackTrace();
		}finally {
			DBUtil.close(sta, conn);
		}
		// 判斷是否刪除數據成功
		if(rows > 0){
			System.out.println("註銷賬戶成功!");
			user = null;
			start();
			return;
		}
	}

4、事務問題

當涉及到事務問題時可以使用的方法有:

  • 使用**conn.setAutoCommit(false)**方法設置手動提交事務
  • 使用方法**conn.commit()**提交事務
  • 使用方法**conn.rollback()**回滾事務。

模擬轉賬:

/**
	 * 模擬轉賬
	 */
	public static void change(){
		Connection conn = null;
		PreparedStatement sta = null;
		try {
			// 獲取數據庫的連接
			conn = DBUtil.getConnection();
			// 設置手動提交
			conn.setAutoCommit(false);
			// 準備sql語句
			String sql1 = "update emp set sal = 2000 where empno = 7369";
			sta = conn.prepareStatement(sql1);
			int rows1 = sta.executeUpdate();
			
			// 準備sql語句
			String sql2 = "update emp set sal = 10000 where empno = 7839";
			sta = conn.prepareStatement(sql2);
			int rows2 = sta.executeUpdate();
			
			if(rows1 > 0 && rows2 > 0){
				// 提交事務
				conn.commit();
				System.out.println("修改工資成功");
			}else{
				// 事務回滾
				conn.rollback();
				System.out.println("修改工資失敗");
			}
			
		} catch (SQLException e) {
			System.out.println("修改工資異常");
			e.printStackTrace();
		}finally{
			// 關閉資源
			DBUtil.close(sta, conn);
		}
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章