JDBC JDBC的開發步驟 DriverManager Connection Statement ResultSet JDBC的資源釋放 JDBC的配置信息提取到配置文件

 JDBC的概述

     什麼是JDBC

 什麼是數據庫驅動

驅動:兩個設備(應用)之間通信的橋樑。

 爲什麼學習JDBC

沒有JDBC的時候,如果現在要開發一套系統,使用Java連接MySQL數據庫,那麼這時候Java程序員需要了解MySQL驅動API,如果使用Java連接Oracle數據庫,那麼這個時候Java程序員需要了解Oracle數據庫驅動API

SUN公司提供一套統一的規範(接口)。然後各個數據庫生產商提供這套接口的實現。這套接口規範就是JDBC的規範。

 JDBC的入門

 JDBC的環境準備

 創建數據庫和表

create database web_test;
use web_test;
create table user(
	id int primary key auto_increment,
	username varchar(20),
	password varchar(20),
	nickname varchar(20),
	age int
);
insert into user values (null,'aaa','123','小麗',34);
insert into user values (null,'bbb','123','大王',32);
insert into user values (null,'ccc','123','小明',28);
insert into user values (null,'ddd','123','大黃',21);

 創建項目,引入jar

 JDBC的代碼實現

 JDBC的開發步驟

 第一步:加載驅動

 第二步:獲得連接

 第三步:基本操作

 第四步:釋放資源

JDBC的代碼實現
import org.junit.Test;

/**
 * JDBC的入門程序
 * @author jt
 *
 */
public class JDBCDemo {

	@Test
	/**
	 * JDBC的入門
	 */
	public void demo1() throws Exception{
		// 1.加載驅動
		Class.forName("com.mysql.jdbc.Driver");
		// 2.獲得連接
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web_test3", "root", "root");
		// 3.基本操作:執行SQL
		// 3.1獲得執行SQL語句的對象
		Statement statement = conn.createStatement();
		// 3.2編寫SQL語句:
		String sql = "select * from user";
		// 3.3執行SQL:
		ResultSet rs = statement.executeQuery(sql);
		// 3.4遍歷結果集:
		while(rs.next()){
			System.out.print(rs.getInt("id")+" ");
			System.out.print(rs.getString("username")+" ");
			System.out.print(rs.getString("password")+" ");
			System.out.print(rs.getString("nickname")+" ");
			System.out.print(rs.getInt("age"));
			System.out.println();
		}
		// 4.釋放資源
		rs.close();
		statement.close();
		conn.close();
	}
}

 JDBCAPI詳解之DriverManager

 DriverManager:驅動管理類

  作用一:註冊驅動


這個方法可以完成驅動的註冊,但是實際開發中一般不會使用這個方法完成驅動的註冊!!!

原因:

如果需要註冊驅動,就會使用DriverManager.registerDriver(new Driver());,但是查看源代碼發現,在代碼中有一段靜態代碼塊,靜態代碼塊已經調用了註冊驅動的方法。

 如果再手動調用該方法註冊驅動,就會導致驅動被註冊兩次。實際開發中一般會採用:

 作用二:獲得連接

這個方法就是用來獲得與數據庫連接的方法:這個方法中有三個參數:
url			:與數據庫連接的路徑
user			:與數據庫連接的用戶名
password		:與數據庫連接的密碼
主要關注的是url的寫法:
jdbc:mysql://localhost:3306/web_test3
jdbc			:連接數據庫的協議
mysql		:是jdbc的子協議
localhost		:連接的MySQL數據庫服務器的主機地址。(連接是本機就可以寫成localhost),如果連接不是本機的,就需要寫上連接主機的IP地址。
3306		:MySQL數據庫服務器的端口號
web_test	:數據庫名稱
url如果連接的是本機的路徑,可以簡化爲如下格式:
jdbc:mysql:///web_test3

 JDBCAPI詳解之Connection

 Connection:與數據庫連接對象

 作用一:創建執行SQL語句的對象



執行SQL語句對象:

l Statement :執行SQL

l CallableStatement :執行數據庫中存儲過程

PreparedStatement :執行SQL.SQL進行預處理。解決SQL注入漏洞 

作用二:管理事務





 JDBCAPI詳解之Statement

 Statement:執行SQL

 作用一:執行SQL



 執行SQL的方法

 boolean execute(String sql);

 執行查詢,修改,添加,刪除的SQL語句。

 ResultSet executeQuery(String sql);

 執行查詢(執行select語句)。

 int executeUpate(String sql);

 執行修改,添加,刪除的SQL語句。

作用二:執行批處理


 JDBCAPI詳解之ResultSet

 ResultSet:結果集。

通過select語句的查詢結果。

 結果集的遍歷

l 結果集遍歷原理

代碼實現

結果集的獲取


 結果集獲取可以使用結果集中的:

getXXX();方法通常都會有一個重載的方法。

 getXXX(int columnIndex);

getXXX(String columnName);


JDBC的資源釋放

 JDBC資源釋放

JDBC程序執行結束後,將與數據庫進行交互的對象釋放掉,通常是ResultSet,Statement,Connection

這幾個對象中尤其是Connection對象是非常稀有的。這個對象一定要做到儘量晚創建,儘早釋放掉。

 將資源釋放的代碼寫入到finally的代碼塊中。

 資源釋放的代碼應該寫的標準:

	if(rs !=null){
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}				
				rs = null;
			}			
			if(statement !=null){
				try {
					statement.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}				
				statement = null;
			}						
			if(conn !=null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}				
				conn = null;
			}

JDBC的CRUD操作之保存操作
保存操作代碼實現
	@Test
	/**
	 * 保存操作的代碼實現
	 */
	public void demo(){
		Connection conn = null;
		Statement stmt = null;
		try{
			// 註冊驅動:
			Class.forName("com.mysql.jdbc.Driver");
			// 獲得連接:
			conn = DriverManager.getConnection("jdbc:mysql:///web_test", "root", "root");
			// 執行操作:
			// 創建執行SQL語句對象:
			stmt = conn.createStatement();
			// 編寫SQL語句:
			String sql = "insert into user values (null,'eee','123','阿黃',21)";
			// 執行SQL語句:
			int num = stmt.executeUpdate(sql);
			if(num > 0){
				System.out.println("保存用戶成功!!!");
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			// 資源釋放:
			if(stmt != null){
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				
				stmt = null;
			}
			if(conn != null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				conn = null;
			}
		}
	}
JDBC的CURD操作之修改操作
修改操作代碼實現
	@Test
	/**
	 * 修改操作的代碼實現
	 */
	public void demo2(){
		Connection conn = null;
		Statement stmt  = null;
		try{
			// 註冊驅動:
			Class.forName("com.mysql.jdbc.Driver");
			// 獲得連接
			conn = DriverManager.getConnection("jdbc:mysql:///web_test", "root", "abc");
			// 執行操作:
			// 創建執行SQL語句的對象:
			stmt = conn.createStatement();
			// 編寫SQL語句:
			String sql = "update user set password='abc',nickname='旺財' where id = 5";
			// 執行SQL語句:
			int num = stmt.executeUpdate(sql);
			if(num > 0){
				System.out.println("修改用戶成功!!!");
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			// 資源釋放:
			if(stmt != null){
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				
				stmt = null;
			}
			if(conn != null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				conn = null;
			}
		}
	}
JDBC的CRUD操作之刪除操作
刪除操作的代碼實現
	@Test
	/**
	 * 刪除操作的代碼實現
	 */
	public void demo3(){
		Connection conn = null;
		Statement stmt = null;
		try{
			// 註冊驅動:
			Class.forName("com.mysql.jdbc.Driver");
			// 獲得連接:
			conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "abc");
			// 創建執行SQL語句對象:
			stmt = conn.createStatement();
			// 編寫SQL:
			String sql = "delete from user where id = 5";
			// 執行SQL:
			int num = stmt.executeUpdate(sql);
			if(num > 0){
				System.out.println("刪除用戶成功!!!");
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			// 資源釋放:
			if(stmt != null){
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				
				stmt = null;
			}
			if(conn != null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				conn = null;
			}
		}
	}

JDBC的CRUD操作之查詢操作
查詢多條記錄
	@Test
	/**
	 * 查詢多條記錄
	 */
	public void demo4(){
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try{
			// 註冊驅動
			Class.forName("com.mysql.jdbc.Driver");
			// 獲得連接
			conn = DriverManager.getConnection("jdbc:mysql:///web_test", "root", "root");
			// 執行操作
			// 創建執行SQL語句的對象:
			stmt = conn.createStatement();
			// 編寫SQL:
			String sql = "select * from user";
			// 執行SQL:
			rs = stmt.executeQuery(sql);
			// 遍歷結果集:
			while(rs.next()){
				System.out.println(rs.getInt("id")+" "+rs.getString("username")+" "+rs.getString("password"));
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			// 資源釋放:
			if(rs != null){
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				
				rs = null;
			}
			if(stmt != null){
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				
				stmt = null;
			}
			if(conn != null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				conn = null;
			}
		}
	}
查詢一條記錄
	@Test
	/**
	 * 查詢一條記錄
	 */
	public void demo5(){
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try{
			// 註冊驅動
			Class.forName("com.mysql.jdbc.Driver");
			// 獲得連接
			conn = DriverManager.getConnection("jdbc:mysql:///web_test", "root", "root");
			// 執行SQL
			// 創建執行SQL語句對象:
			stmt = conn.createStatement();
			// 編寫SQL:
			String sql = "select * from user where id = 4";
			rs = stmt.executeQuery(sql);
			// 判斷就可以:
			if(rs.next()){
				System.out.println(rs.getInt("id")+" "+rs.getString("username")+" "+rs.getString("password"));
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			// 資源釋放:
			if(rs != null){
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				
				rs = null;
			}
			if(stmt != null){
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				
				stmt = null;
			}
			if(conn != null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				conn = null;
			}
		}
	}

JDBC的工具類的抽取
抽取一個JDBC的工具類
因爲傳統JDBC的開發,註冊驅動,獲得連接,釋放資源這些代碼都是重複編寫的。所以可以將重複的代碼提取到一個類中來完成。
/**
 * JDBC的工具類
 * @author jt
 *
 */
public class JDBCUtils {
	private static final String driverClassName;
	private static final String url;
	private static final String username;
	private static final String password;
	
	static{
		driverClassName="com.mysql.jdbc.Driver";
		url="jdbc:mysql:///web_test";
		username="root";
		password="root";
	}

	/**
	 * 註冊驅動的方法
	 */
	public static void loadDriver(){
		try {
			Class.forName(driverClassName);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 獲得連接的方法
	 */
	public static Connection getConnection(){
		Connection conn = null;
		try{
			// 將驅動一併註冊:
			loadDriver();
			// 獲得連接
			conn = DriverManager.getConnection(url,username, password);
		}catch(Exception e){
			e.printStackTrace();
		}
		return conn;
	}
	
	/**
	 * 釋放資源的方法
	 */
	public static void release(Statement stmt,Connection conn){
		if(stmt != null){
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
			stmt = null;
		}
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			conn = null;
		}
	}
	
	public static void release(ResultSet rs,Statement stmt,Connection conn){
		// 資源釋放:
		if(rs != null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
			rs = null;
		}
		if(stmt != null){
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
			stmt = null;
		}
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			conn = null;
		}
	}
}
1.1.2測試工具類
	@Test
	/**
	 * 查詢操作:使用工具類
	 */
	public void demo1(){
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try{
			// 獲得連接:
			conn = JDBCUtils.getConnection();
			// 創建執行SQL語句的對象:
			stmt = conn.createStatement();
			// 編寫SQL:
			String sql = "select * from user";
			// 執行查詢:
			rs = stmt.executeQuery(sql);
			// 遍歷結果集:
			while(rs.next()){
				System.out.println(rs.getInt("id")+" "+rs.getString("username")+" "+rs.getString("password"));
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			// 釋放資源:
			JDBCUtils.release(rs, stmt, conn);
		}
	}

 JDBC的配置信息提取到配置文件

 配置文件

 屬性文件

 格式:擴展名是.properties

 內容:key=value

 XML文件

 提取信息到配置文件

 定義一個配置文件

 在工具類中解析屬性文件

獲取到具體內容爲常量賦值

 JDBCSQL注入漏洞

 什麼是SQL注入漏洞

在早期互聯網上SQL注入漏洞普遍存在。有一個網站,用戶需要進行註冊,用戶註冊以後根據用戶名和密碼完成登錄。假設現在用戶名已經被其他人知道了,但是其他人不知道你的密碼,也可以登錄到網站上進行相應的操作。

演示SQL注入漏洞

基本登錄功能實現

演示SQL注入漏洞
輸入用戶名
aaa’ or ‘1=1 密碼隨意
aaa’ --      密碼隨意

 JDBCSQL注入漏洞分析和解決

 SQL注入漏洞分析

 SQL注入漏洞解決

需要採用PreparedStatement對象解決SQL注入漏洞。這個對象將SQL預先進行編譯,使用?作爲佔位符。?所代表內容是SQL所固定。再次傳入變量(包含SQL的關鍵字)。這個時候也不會識別這些關鍵字。


public class UserDao {
	
	public boolean login(String username,String password){
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		// 定義一個變量:
		boolean flag = false;
		try{
			// 獲得連接:
			conn = JDBCUtils.getConnection();
			// 編寫SQL語句:
			String sql = "select * from user where username = ? and password = ?";
			// 預編譯SQL
			pstmt = conn.prepareStatement(sql);
			// 設置參數:
			pstmt.setString(1, username);
			pstmt.setString(2, password);
			// 執行SQL語句:
			rs = pstmt.executeQuery();
			if(rs.next()){
				// 說明根據用戶名和密碼可以查詢到這條記錄
				flag = true;
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			JDBCUtils.release(rs, pstmt, conn);
		}
		return flag;
	}

 JDBCCRUD操作之PreparedStatement的保存操作

 保存操作代碼實現

	@Test
	/**
	 * 保存操作
	 */
	public void demo1(){
		Connection conn = null;
		PreparedStatement pstmt = null;
		try{
			// 獲得連接:
			conn = JDBCUtils.getConnection();
			// 編寫SQL語句:
			String sql = "insert into user values (null,?,?,?,?)";
			// 預編譯SQL:
			pstmt = conn.prepareStatement(sql);
			// 設置參數:
			pstmt.setString(1, "eee");
			pstmt.setString(2, "abc");
			pstmt.setString(3, "旺財");
			pstmt.setInt(4, 32);
			// 執行SQL
			int num = pstmt.executeUpdate();
			if(num > 0){
				System.out.println("保存成功!");
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			JDBCUtils.release(pstmt, conn);
		}
	}

 JDBCCRUD操作之PreparedStatement的修改操作

 修改操作代碼實現

@Test
	/**
	 * 修改操作
	 */
	public void demo2(){
		Connection conn = null;
		PreparedStatement pstmt = null;
		try{
			// 獲得連接:
			conn = JDBCUtils.getConnection();
			// 編寫SQL語句:
			String sql = "update user set username = ?,password =?,nickname=?,age = ? where id = ?";
			// 預編譯SQL:
			pstmt = conn.prepareStatement(sql);
			// 設置參數:
			pstmt.setString(1, "abc");
			pstmt.setString(2, "1234");
			pstmt.setString(3, "旺旺");
			pstmt.setInt(4, 23);
			pstmt.setInt(5, 6);
			// 執行SQL:
			int num = pstmt.executeUpdate();
			if(num > 0){
				System.out.println("修改成功!");
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			JDBCUtils.release(pstmt, conn);
		}
	}

 JDBCCRUD操作之PreparedStatement的刪除操作

 刪除操作的代碼實現

	@Test
	/**
	 * 刪除操作
	 */
	public void demo3(){
		Connection conn = null;
		PreparedStatement pstmt  = null;
		try{
			// 獲得連接:
			conn = JDBCUtils.getConnection();
			// 編寫SQL語句:
			String sql = "delete from user where id = ?";
			// 預編譯SQL
			pstmt = conn.prepareStatement(sql);
			// 設置參數:
			pstmt.setInt(1, 4);
			// 執行SQL:
			int num = pstmt.executeUpdate();
			if(num > 0){
				System.out.println("刪除成功!");
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			JDBCUtils.release(pstmt, conn);
		}
	}

 JDBCCRUD操作之PreparedStatement的查詢操作

 查詢操作代碼實現

@Test
	/**
	 * 查詢操作
	 */
	public void demo4(){
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try{
			// 獲得連接:
			conn = JDBCUtils.getConnection();
			// 編寫SQL:
			String sql = "select * from user";
			// 預編譯SQL:
			pstmt = conn.prepareStatement(sql);
			// 設置參數:
			// 執行SQL:
			rs = pstmt.executeQuery();
			// 遍歷結果集:
			while(rs.next()){
				System.out.println(rs.getInt("id")+" "+rs.getString("username")+" "+rs.getString("password")+" "+rs.getString("nickname"));
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			JDBCUtils.release(rs, pstmt, conn);
		}
	}

 JDBC的批處理操作

 什麼是批處理

之前進行JDBC的操作的時候,都是一條SQL語句執行。現在如果使用批處理,可以將一批SQL一起執行。

批處理基本使用
	@Test
	/**
	 * 批處理基本操作
	 */
	public void demo1(){
		Connection conn = null;
		Statement stmt = null;
		try{
			// 獲得連接:
			conn = JDBCUtils.getConnection();
			// 創建執行批處理對象:
			stmt = conn.createStatement();
			// 編寫一批SQL語句:
			String sql1 = "create database test1";
			String sql2 = "use test1";
			String sql3 = "create table user(id int primary key auto_increment,name varchar(20))";
			String sql4 = "insert into user values (null,'aaa')";
			String sql5 = "insert into user values (null,'bbb')";
			String sql6 = "insert into user values (null,'ccc')";
			String sql7 = "update user set name = 'mmm' where id = 2";
			String sql8 = "delete from user where id = 1";
			// 添加到批處理
			stmt.addBatch(sql1);
			stmt.addBatch(sql2);
			stmt.addBatch(sql3);
			stmt.addBatch(sql4);
			stmt.addBatch(sql5);
			stmt.addBatch(sql6);
			stmt.addBatch(sql7);
			stmt.addBatch(sql8);
			// 執行批處理:
			stmt.executeBatch();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			JDBCUtils.release(stmt, conn);
		}
	}
批量插入(使用PreparedStatement)
	@Test
	/**
	 * 批量插入記錄:
	 * * 默認情況下MySQL批處理沒有開啓的,需要在url後面拼接一個參數即可。
	 */
	public void demo2(){
		// 記錄開始時間:
		long begin = System.currentTimeMillis();
		Connection conn = null;
		PreparedStatement pstmt = null;
		try{
			// 獲得連接:
			conn = JDBCUtils.getConnection();
			// 編寫SQL語句:
			String sql = "insert into user values (null,?)";
			// 預編譯SQL:
			pstmt = conn.prepareStatement(sql);
			for(int i=1;i<=10000;i++){
				pstmt.setString(1, "name"+i);
				// 添加到批處理
				pstmt.addBatch();
				// 注意問題:
				// 執行批處理
				if(i % 1000 == 0){
					// 執行批處理:
					pstmt.executeBatch();
					// 清空批處理:
					pstmt.clearBatch();
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			JDBCUtils.release(pstmt, conn);
		}
		long end = System.currentTimeMillis();
		System.out.println((end-begin));
	}

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