【學習筆記】JDBC和MySQL

1.JDBC概述

JDBC(Java DataBase Connectivity)就是Java數據庫鏈接
早期SUN公司的天才們想編寫一套能夠鏈接天下全部數據庫的API,可是當他們剛剛開始時就發現這是不可完成的任務,由於各個廠商的數據庫服務器差別太大了。後來SUN開始與數據庫廠商們討論,最終得出的結論是,由SUN提供一套訪問數據庫的規範(就是一組接口),並提供鏈接數據庫的協議標準,而後各個數據庫廠商會遵循SUN的規範,提供一套訪問本身公司的數據庫服務器的API。SUN提供的規範命名爲JDBC,而各個廠商提供的,遵循了JDBC規範的,能夠訪問本身數據庫的API被稱之爲驅動!JDBC是接口,而JDBC驅動(相關jar包)纔是接口的實現,沒有驅動沒法完成數據庫鏈接!每一個數據庫廠商都有本身的驅動,用來鏈接本身公司的數據庫。java

2.JDBC核心類(接口)介紹

JDBC中的核心類有:DriverManager、Connection、PreparedStatement,和ResultSetmysql

(1)DriverManger(驅動管理器)的做用有兩個:web

  1. 註冊驅動:這可讓JDBC知道要使用的是哪一個驅動
  2. 獲取Connection:若是能夠獲取到Connection,那麼說明已經與數據庫鏈接上了。

(2)Connection:Connection對象表示鏈接,與數據庫的通信都是經過這個對象展開的sql

  •      Connection最爲重要的一個方法就是用來獲取PreparedStatement對象

(3)PreparedStatement是用來向數據庫發送SQL語句的,這樣數據庫就會執行發送過來的SQL語句.他有兩個重要方法:數據庫

  • int executeUpdate(String sql):執行更新操做(insert、update、delete等),返回更新的條數(int類型)
  • ResultSet executeQuery(String sql):執行查詢操做,返回查詢結果ResultSet

(4)ResultSet對象表示查詢結果集,只有在執行查詢操做後纔會有結果集的產生。結果集是一個二維的表格,有行有列。操做結果集要移動ResultSet內部的「行光標」,以及獲取當前行上的每一列上的數據:服務器

  • boolean next():使「行光標」移動到下一行,並返回移動後的行是否存在;
  • XXX getXXX(int col):獲取當前行指定列上的值,參數就是列數,列數從1開始,而不是0。

操做光標的方法有兩類:一類用來判斷遊標位置的,另外一類是用來移動遊標的。光標的移動是一行一行的移動url

3.代碼訪問數據庫

MySQL驅動包:mysql-connector-java-5.1.39-bin.jarspa

(1)原始方法訪問數據庫code

public class JDBCUtils_V1 {

	public static Connection getConnection() {
		Connection conn = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");//註冊驅動
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web08", "root", "root");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return conn;
	}

	public static void release(Connection conn, PreparedStatement pstmt, ResultSet rs) {
    ......
	}
}

public class MyTest001 {
	public static void main(String[] args) throws SQLException {
		Connection conn = JDBCUtils_V1.getConnection();
		String sql="select * from user";
		PreparedStatement prepareStatement = conn.prepareStatement(sql);
		ResultSet resuleSet = prepareStatement.executeQuery();
		while(resuleSet.next()) {
			System.out.println(resuleSet.getObject(2));
		}
		
	    JDBCUtils_V1.release(conn, prepareStatement, resuleSet);
		
	}

}

(2)使用ResourceBundle讀取properties文件訪問數據庫對象

DRIVER=com.mysql.jdbc.Driver
URL=jdbc:mysql://localhost:3306/user
Username:root
Password:123


public class JDBCUtils_V2 {
	private static String driver;
	private static String url;
	private static String username;
	private static String password;
	
	/**
	 * 靜態代碼塊加載配置文件信息
	 */
	static{
		ResourceBundle bundle = ResourceBundle.getBundle("db");
		driver = bundle.getString("driver");
		url = bundle.getString("url");
		username = bundle.getString("username");
		password = bundle.getString("password");
	}


	public static Connection getConnection() {
		Connection conn = null;
		try {
			Class.forName(driver);
			conn = DriverManager.getConnection(url, username, password);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return conn;
	}

	public static void release(Connection conn, PreparedStatement pstmt, ResultSet rs) {
	}
}

(3)使用類加載器的classLoader.getResourceAsStream("db.properties");方法讀取properties配置文件來鏈接數據庫

public class JDBCUtils_V3 {
	private static String driver;
	private static String url;
	private static String username;
	private static String password;

	/**
	 * 靜態代碼塊加載配置文件信息
	 */
	static {
		try {
			// 1.經過當前類獲取類加載器
			ClassLoader classLoader = JDBCUtils_V3.class.getClassLoader();
			// 2.經過類加載器的方法得到一個輸入流
			InputStream is = classLoader.getResourceAsStream("db.properties");
			// 3.建立一個properties對象
			Properties props = new Properties();
			// 4.加載輸入流
			props.load(is);
			// 5.獲取相關參數的值
			driver = props.getProperty("driver");
			url = props.getProperty("url");
			username = props.getProperty("username");
			password = props.getProperty("password");
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * 獲取鏈接方法
	 */
	public static Connection getConnection() {
		Connection conn = null;
		try {
			Class.forName(driver);
			conn = DriverManager.getConnection(url, username, password);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return conn;
	}

	public static void release(Connection conn, PreparedStatement pstmt, ResultSet rs) {
      }
}

4.SQL攻擊

在須要用戶輸入的地方,用戶輸入的是SQL語句的片斷,最終用戶輸入的SQL片斷與咱們DAO中寫的SQL語句合成一個完整的SQL語句!例如用戶在登陸時輸入的用戶名和密碼都是爲SQL語句的片斷!

在登陸頁面輸入參數:‘a' or 'a'='a", "a' or 'a'='a‘
這會使咱們登陸成功!由於是輸入的用戶名和密碼是SQL語句片斷,最終與咱們的login()方法中的SQL語句組合在一塊兒!組合在一塊兒的SQL語句:

SELECT * FROM user WHERE username='a' or 'a'='a' and password='a' or 'a'='a'

  • 使用PreparedStatement能夠防止SQL攻擊。PreparedStatement叫預編譯聲明,是Statement的子接口,可使用PreparedStatement來替換Statement。
  • PreparedStatement相比於Statement,最大的好處就是在於重複使用同一模板,給予其不一樣的參數來重複的使用它。這纔是真正提升效率的緣由。

5.MySQL相關內容

5.1表與表的關係

(1)主表---主鍵,從表---外鍵字段

聲明外鍵約束語法:alter  table  從表  add [ constraint ]  外鍵名稱 foreignkey  從表外鍵字段名  references  主表(主表的主鍵)

注:外鍵名稱用於刪除外鍵約束(alter table 從表 drop foreignkey 外鍵名稱),通常建議以「_fk」結尾

一對多(一個主鍵對應多個外鍵):分類表和商品表的關係以下:

多對多(多個主鍵對應多個外鍵):訂單表,訂單項表和商品表

5.2 多表查詢語句

*student表和score分數表

(1)內鏈接:結果僅包含符合鏈接條件的兩表中的行。兩種寫法

(2)外鏈接。結果包含符合條件的行,同時包含不符合條件的行(分爲左外鏈接、右外鏈接和全外鏈接)

左外鏈接:左表所有行+右表匹配的行,若是左表中某行 在右表中沒有匹配的行,則右表該行顯示NULL。以下:

右外鏈接:右表所有行+左表匹配的行。以下:

相關文章
相關標籤/搜索