# JDBC API ## 獲取資料庫連接5種方式 1. 通過new創建Driver對象; 2. 使用反射載入Driver類,動態載入,減少依賴性,更加靈活; 3. 使用DriverManager 替代 Driver 進行統一管理,有了更好的擴展性; 4. 使用 Class.forName 自動完成 ...
JDBC API
獲取資料庫連接5種方式
- 通過new創建Driver對象;
- 使用反射載入Driver類,動態載入,減少依賴性,更加靈活;
- 使用DriverManager 替代 Driver 進行統一管理,有了更好的擴展性;
- 使用 Class.forName 自動完成註冊驅動,簡化代碼;
- 在方式4的基礎上改進,增加配置文件,讓mysql連接更靈活,最推薦使用;
代碼演示:
package com.hspedu.jdbc;
import com.mysql.jdbc.Driver;
import org.junit.jupiter.api.Test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
/**
* 分析java連接mysql的5種方式
*/
public class JdbcConn {
//方式1
@Test
public void connect01() throws SQLException {
Driver driver = new Driver();
String url = "jdbc:mysql://localhost:3306/jdbc_learning";
Properties properties = new Properties();
properties.setProperty("user", "root");//用戶名
properties.setProperty("password", "root");//密碼
Connection connection = driver.connect(url, properties);
System.out.println("第一種方式" + connection);
connection.close();
}
//方式2
@Test
public void connect02() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
//使用反射載入Driver類,動態載入,減少依賴性,更加靈活
Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver) aClass.newInstance();
String url = "jdbc:mysql://localhost:3306/jdbc_learning";
Properties properties = new Properties();
properties.setProperty("user", "root");//用戶名
properties.setProperty("password", "root");//密碼
Connection connection = driver.connect(url, properties);
System.out.println("第二種方式" + connection);
connection.close();
}
//方式3 使用DriverManager 替代 Driver 進行統一管理,有了更好的擴展性
@Test
public void connect03() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
//使用反射載入Driver類
Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver) aClass.newInstance();
String url = "jdbc:mysql://localhost:3306/jdbc_learning";
String user = "root";
String password = "root";
DriverManager.registerDriver(driver);//註冊Driver驅動,DriverManager是Java自帶的類
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println("第三種方式" + connection);
}
//方式4 使用 Class.forName 自動完成註冊驅動,簡化代碼
//這種方式推薦使用,使用最多
@Test
public void connect04() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
//使用反射載入Driver類
//在載入 Driver類時,完成註冊
/*
源碼:1. 靜態代碼塊,在類載入時,會執行一次
2. 因此註冊driver的工作在底層已經完成了
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
*/
//1.mysqL驅動5.1.6可以無需CLass.forName("com.mysql.jdbc.Driver");
//2.從jdk1.5以後使用了jdbc4,不再需要顯示調用class.forName()註冊驅動而是自動調用驅動
//jar包下META-INF\services\java.sql.Driver文本中的類名稱去註冊
//3.建議還是寫上CLass.forName("com.mysql.jdbc.Driver"),更加明確
Class.forName("com.mysql.jdbc.Driver");//內部有一段靜態代碼會預設自動註冊
String url = "jdbc:mysql://localhost:3306/jdbc_learning";
String user = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println("第四種方式" + connection);
}
//方式5 在方式4的基礎上改進,增加配置文件,讓mysql連接更靈活,最推薦使用
@Test
public void connect05() throws IOException, ClassNotFoundException, SQLException {
//通過Properties對象獲取配置文件的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//獲取相關的值
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
Class.forName(driver);//建議寫上
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println("第五種方式" + connection);
}
}
配置文件mysql.properties:
user=root
password=zyl
url=jdbc:mysql://localhost:3306/jdbc_learning
driver=com.mysql.jdbc.Driver
ResultSet[結果集]
-
基本介紹
- 表示資料庫結果集的數據表,通常通過執行查詢資料庫的語句生成;
- ResultSet對象保持一個游標指向其當前的數據行。最初,游標位於第一行前;
- next方法將游標移動到下一行,並且由於在ResultSet對象中沒有更多行時返回false,因此可以在while迴圈中使用迴圈來遍歷結果集。
-
代碼演示:
package com.hspedu.jdbc.resultset_; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.sql.*; import java.util.Properties; /** * @author: 86199 * @date: 2023/6/14 21:52 * Description: 演示select 語句 返回 ResultSet,並取出結果 */ @SuppressWarnings({"all"}) public class ResultSet_ { public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException { //通過Properties對象獲取配置文件的信息 Properties properties = new Properties(); properties.load(new FileInputStream("src\\mysql.properties")); //獲取相關的值 String user = properties.getProperty("user"); String password = properties.getProperty("password"); String driver = properties.getProperty("driver"); String url = properties.getProperty("url"); //1. 註冊驅動 Class.forName(driver);//建議寫上 //2. 得到連接 Connection connection = DriverManager.getConnection(url, user, password); //3. 得到Statement Statement statement = connection.createStatement(); //組織sql語句 String sql = "select id, name, sex, borndate from actor;"; /* 1 周星馳 男 1970-11-11 00:00:00 110 2 劉德華 男 1970-11-11 00:00:00 110 3 劉德華 男 1970-11-11 00:00:00 110 */ //執行給定的SQL語句,該語句返回單個ResultSet對象 /* 源碼: */ ResultSet resultSet = statement.executeQuery(sql); while (resultSet.next()) {//讓游標後移,如果沒有更多行,則返回false int id = resultSet.getInt(1);//獲取該行的第1列 String name = resultSet.getString(2);//獲取該行的第2列 String sex = resultSet.getString(3); String date = resultSet.getString(4); System.out.println(id + "\t" + name + "\t" + sex + "\t" + date); } //關閉資源 resultSet.close(); statement.close(); connection.close(); } }
## Statement對象
- **基本介紹**
1. Statement對象,用於執行靜態SQL語句並返回其生成的結果的對象。
2. 在連接建立之後,需要對資料庫進行訪問,執行命名或是SQL語句,可以通過
- Statement [存在SQL註入]
- ==PreparedStatement==(預處理)
- CallableStatement(存儲過程)
3. Statement對象執行SQL語句存在==SQL註入==的風險
- **SQL註入**是利用某些系統沒有對用戶輸入的數據進行充分的檢查,而在用戶輸入數據中註入非法的SQL語句段或命令,惡意攻擊資料庫。
- 要防範 SQL註入,只要用 **PreparedStatement**(從Statement擴展而來)取代 Statement 就可以了。
**MySQL代碼:**
```mysql
-- 演示sql註入
-- 創建一張表
CREATE TABLE admin ( -- 管理員表
`name` VARCHAR(32) NOT NULL UNIQUE,
pwd VARCHAR(32) NOT NULL DEFAULT '') CHARACTER SET utf8;
-- 添加數據
INSERT INTO admin VALUES('jac', '123');
-- 查找某個管理員是否存在
SELECT *
FROM admin
WHERE `name` = 'tom' AND pwd = '123';
-- SQL註入
-- 輸入用戶名 1' or
-- 輸入密碼 為 or '1' = '1
-- SELECT *
-- FROM admin
-- WHERE `name` = '' AND pwd = '';
SELECT *
FROM admin
WHERE `name` = '1' or' AND pwd = 'or '1' = '1';
Java代碼:
package com.hspedu.jdbc.statement_;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;
/**
* @author: 86199
* @date: 2023/6/15 22:24
* Description: 演示 SQL註入的問題
*/
public class Statement_ {
public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
Scanner scanner = new Scanner(System.in);
//讓用戶輸入管理員用戶名和密碼
System.out.print("請輸入管理員名字:");
String admin_name = scanner.nextLine();
System.out.print("請輸入管理員密碼:");
String admin_pwd = scanner.nextLine();
//通過Properties對象獲取配置文件的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//獲取相關的值
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
//1. 註冊驅動
Class.forName(driver);//建議寫上
//2. 得到連接
Connection connection = DriverManager.getConnection(url, user, password);
//3. 得到Statement
Statement statement = connection.createStatement();
//組織sql語句
String sql = "SELECT name, pwd FROM admin where name = '"
+ admin_name + "' and pwd = '" + admin_pwd + "';";
ResultSet resultSet = statement.executeQuery(sql);
if (resultSet.next()) {//如果查詢到一條記錄,說明該管理員存在
System.out.println("恭喜,登錄成功");
}else{
System.out.println("對不起,登錄失敗");
}
resultSet.close();
statement.close();
connection.close();
}
}
//運行
/*
請輸入管理員名字:1' or
請輸入管理員密碼:or '1' = '1
恭喜,登錄成功
*/
預處理(查詢和修改)
- PreparedStatement 執行的SQL語句中的參數用問號(?)來表示,調用 PreparedStatement 對象的 setXxx() 方法來設置這些參數。setXxx() 方法有兩個參數,第一個參數都是int,要設置SQL語句中的參數的索引(從 1 開始),第二個是設置的 SQL 語句中的參數的值。
- 調用 executeQuery(),返回 ResultSet 對象。
- 調用 executeUpdate():執行更新,包括增,刪,修改
package com.hspedu.jdbc.preparedstatement_;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;
/**
* @author: 86199
* @date: 2023/7/17 20:43
* Description: 演示PreparedStatement使用
*/
public class PreparedStatement_ {
public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
Scanner scanner = new Scanner(System.in);
//讓用戶輸入管理員用戶名和密碼
System.out.print("請輸入管理員名字:");
String admin_name = scanner.nextLine();
System.out.print("請輸入管理員密碼:");
String admin_pwd = scanner.nextLine();
//通過Properties對象獲取配置文件的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//獲取相關的值
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
//1. 註冊驅動
Class.forName(driver);//建議寫上
//2. 得到連接
Connection connection = DriverManager.getConnection(url, user, password);
//sql中的?就相當於占位符
String sql = "SELECT name, pwd FROM admin where name = ? and pwd = ? ;";
//3. 得到PreparedStatement,這裡的statement是實現了PreparedStatement介面的實現類的對象
PreparedStatement statement = connection.prepareStatement(sql);
//給 ? 賦值
statement.setString(1, admin_name);
statement.setString(2, admin_pwd);
//執行sql語句,如果執行的是dml語句要用executeUpdate()
ResultSet resultSet = statement.executeQuery();//()中不能再寫sql語句,不然執行的就是帶?的,填了sql語句就是調用了父類Statement的方法了
if (resultSet.next()) {//如果查詢到一條記錄,說明該管理員存在
System.out.println("恭喜,登錄成功");
}else{
System.out.println("對不起,登錄失敗");
}
//關閉鏈接
resultSet.close();
statement.close();
connection.close();
}
}
//運行
/*
請輸入管理員名字:1' or
請輸入管理員密碼:or '1' = '1
對不起,登錄失敗
*/