Java之JDBC詳談(資料庫)
一、了解JDBC
- JDBC是什麼?
Java DataBase Connectivity(Java語言連接資料庫)
- JDBC的本質
JDBC是SUN公司制定的一套介面(interface)
java.sql.*(這個軟體包下有很多介面)
開始面向介面編程,面向抽象編程,不要面向具體編程。
- JDBC編程六步(需要背會)
- 第一步:註冊驅動(告訴Java程式,即將要連接的是哪個資料庫)
- 第二步:獲取連接
- 第三步:獲取資料庫操作對象(專門執行sql語句的對象)
- 第四步:執行SQL語句(DQL DML)
- 第五步:處理查詢結果集
- 第六步:釋放資源
二、連接資料庫、實現用戶登錄
2.1前期準備
- 還需要導入一個資料庫驅動包,mysql-connector-java-5.1.47.jar
- url:包括協議、IP、PORT(埠)、資源名
- mysql的url:jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf8&useSSL=false
- jdbc:mysql:// 協議
- localhost IP地址
- 3306 mysql資料庫埠號
- smbms 具體的資料庫實例名
public class JdbcTest {
public static void main(String[] args) throws SQLException {
try {
//1、註冊驅動
DriverManager.registerDriver(new com.mysql.jdbc.Driver());//這是一種載入驅動方式
//這是另外一種載入驅動方式,我們從文件中讀資訊
FileInputStream file = new FileInputStream("db.properties");
//創建Map集合對象
Properties properties = new Properties();
//將文件資訊以鍵值對的形式載入出來
properties.load(file);
//還可以使用一個比較簡便的
ResourceBundle bundle = ResourceBundle.getBundle("文件名");
String driver = bundle.getString("key");
//獲取文件資訊
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
//通過反射載入驅動
Class.forName(driver);
System.out.println(driver);
//2、獲取連接
Connection connection = DriverManager.getConnection(url, username, password);
System.out.println(connection);
//3、獲取執行sql的對象
Statement statement = connection.createStatement();
String sql = "select * from smbms_role";
//4、執行sql語句5、返回結果集
ResultSet resultSet = statement.executeQuery(sql);
resultSet.next();
System.out.println(resultSet.getInt("id"));
//6、釋放資源
resultSet.close();
statement.close();
connection.close();
//關閉資源時,必須從小到大按順序關閉,並且每個都要try--catch
} catch (Exception e) {
e.printStackTrace();
}
}
}
//多寫幾遍,多查看API文檔,了解每個類具體幹什麼的,你就懂了,也就學會了。
- 增刪改用int executeUpdate(insert/delete/update)
- 查詢用ResulSet executeQurey(select)
- 查詢時用boolean result.next(),若當前有數據則返回true,若沒有則false
- JDBC的下標時從1開始,而不是0
2.2用戶登錄程式碼實現
public class LoginTest {
public static void main(String[] args) {
//1.獲取用戶登錄資訊
Map<String,String> userInfo = userInfo();
//2.驗證用戶密碼是否正確
boolean loginResult = userLogin(userInfo);
System.out.println(loginResult?"登錄成功" : "登錄失敗");
}
//獲取用戶登錄資訊
public static Map<String,String> userInfo() {
Scanner scan = new Scanner(System.in);
System.out.println("輸入用戶名:");
String username = scan.next();
System.out.println("輸入密碼:");
String password = scan.next();
HashMap<String, String> user = new HashMap<>();
user.put("username",username);
user.put("password",password);
return user;
}
//jdbc
public static boolean userLogin(Map<String,String> userInfo) {
boolean falg = false;
Connection conn = null;
Statement statement = null;
ResultSet resultSet = null;
try {
String username = userInfo.get("username");
String password = userInfo.get("password");
//1.載入驅動
Class.forName("com.mysql.jdbc.Driver");
//2.獲取連接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf8&useSSL=false", "root", "200506lx");
//3.獲取操作對象
statement = conn.createStatement();
//4.執行sql
//5.返回結果
String sql = "select * from smbms_user where userCode = '"+username+"'and userPassword = '"+password+"'";
resultSet = statement.executeQuery(sql);
if(resultSet.next()) {
falg = true;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 6.釋放資源
if(resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return falg;
}
}
三、sql注入問題
asd'or'1'='1
- 解決SQL注入問題
- 只要用戶提供的資訊不參與SQL語句的編譯過程,問題就解決了
- 即使用戶提供的資訊中含有SQL語句的關鍵字,但是沒有參與編譯,不起作用。
- 要想用戶資訊不參與SQL語句的編譯,那麼必須使用java.sql.PreparedStatement
- PreparedStatement這個介面繼承了java.sql.Statement
- 屬於預編譯的資料庫操作對象,預先對SQL語句的框架進行編譯,然後再給SQL語句傳值
public static boolean userLogin(Map<String,String> userInfo) {
boolean falg = false;
Connection conn = null;
PreparedStatement ps = null;//將Statement換成PreparedStatement
ResultSet resultSet = null;
try {
String username = userInfo.get("username");
String password = userInfo.get("password");
//1.載入驅動
Class.forName("com.mysql.jdbc.Driver");
//2.獲取連接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf8&useSSL=false", "root", "200506lx");
//3.獲取操作對象
//一個?就是一個佔位符,接受一個值
String sql = "select * from smbms_user where userCode = ? and userPassword = ?";
ps = conn.prepareStatement(sql);
ps.setString(1,username); //1代表第一個?,給他設置值username
ps.setString(2,password); //JDBC下標從1開始
//4.執行sql
//5.返回結果
resultSet = ps.executeQuery();
if(resultSet.next()) {
falg = true;
}
}
}
四、對比Statement和PreparedStatement
- Statement存在sql注入問題,PreparedStatement解決了sql注入問題
- Statement是編譯一次執行一次,PreparedStatement是編譯一次,可執行n次,效率較高。
- PreparedStatement會在編譯階段做類型檢查
- 但是也有Statement用的地方。
五、JDBC事務演示
- JDBC中只要執行任意一條DML語句,就提交一次
- 記住三行程式碼搞定
conn.setAutoCommit(false)//將自動提交機制修改為手動提交機制,開啟事務
conn.commit();//提交事務
conn.rollback();//事務回滾
六、JDBC工具類的封裝
public class DButil {
/*
工具類中的構造方法都是私有的
因為工具類中的程式碼都是靜態的,不需要new對象,直接採用類名調用
*/
private DButil(){
}
private static final String driver;
private static final String url;
private static final String username;
private static final String password;
//靜態程式碼塊隨著類的載入而載入,並且只載入一次
static {
ResourceBundle rb = ResourceBundle.getBundle("db.properties");
driver = rb.getString("driver");
url = rb.getString("url");
username = rb.getString("username");
password = rb.getString("password");
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//獲取資料庫的連接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,username,password);
}
//資料庫資源關閉
public static void closeResource(Connection conn, PreparedStatement ps, ResultSet rs) {
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
七、結尾
- 對於資料庫的JDBC內容就總結這麼多,若想深入學習等待後續更新,基礎部分掌握這些足矣。如果有不足之處,希望大家多多包涵,多多支援。如果有不懂的地方可以直接私信問我,歡迎來訪!
- 我將會繼續更新關於Java的學習知識,感興趣的小夥伴可以關注一下。
- 文章寫得比較走心,用了很長時間,絕對是copy過來的!
- 尊重每一位學習知識的人,同時也尊重每一位分享知識的人。
- 😎你的點贊與關注,是我努力前行的無限動力。🤩