1.數據庫驅動
想一下我們之前是怎么操作數據庫,是不是使用SQL語句對其mysql數據庫管理系統,然后管理系統在進行數據庫(硬盤文件里面的)進行操作。那么我現在想使用應用程序對其數據庫進行操作,應該怎么辦呢?
那么數據庫驅動就是搭建在應用程序和數據庫之間的橋梁!!!
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
2.JDBC
根據上面的圖可以知道,不同的數據庫就需要使用不同的數據庫驅動進行操作,適合麻煩的,在java上面就需要使用不同的數據庫驅動,是很不方便的!
sun公司為了簡化開發人員對于數據庫的操作,提供了(java操作數據庫的)規范,俗稱JDBC(java database conection顧名思義就是java與數據庫的連接)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
2.1JDBC下載
我使用的mysql版本是8.0,因此我需要下相關的java-connector 8.0.28相對來說穩定一點!
JDBC下載
2.2JDBC的第一個代碼測試
2.2.1前期工作:
? ? ? ? 首先我們需要對其進行jar的導入,導入依賴,(先創建一個lib目錄,然后添加進去就行!注意需要對lib右鍵里面的 add as? library)
2.2.2開始編寫代碼:
數據庫里面的表:
java里面的代碼:
package com.xcl.test;import java.sql.*;public class Demo01 {public static void main(String[] args) throws ClassNotFoundException, SQLException {//1.添加驅動(固定寫法,加載驅動)Class.forName("com.mysql.cj.jdbc.Driver");//2.用戶信息和url//useUnicode=true(表示中文有效) &characterEncoding=utf8(編碼要求) && useSSL=true(一些其他錯誤的警告)String url = "jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&&useSSL=true";String username = "root";String password = "123456";//3.連接成功,數據庫對象(拿到了數據庫對象,現在就可以對其進行操作數據庫對象,connection就代表數據庫)Connection connection = DriverManager.getConnection(url, username, password);//4.執行SQL對象Statement statement = connection.createStatement();//5.執行SQL對象去執行SQL,查看返回結果//SQL語句String sql = "select * from student";//執行結果ResultSet resultSet = statement.executeQuery(sql);while (resultSet.next()){System.out.print("id=" + resultSet.getObject("id"));System.out.print("name=" + resultSet.getObject("name"));System.out.print("password=" + resultSet.getObject("password"));System.out.print("sex=" + resultSet.getObject("sex"));System.out.print("birthday=" + resultSet.getObject("birthday"));System.out.print("address=" + resultSet.getObject("address"));System.out.print("email=" + resultSet.getObject("email"));}//6.釋放連接resultSet.close();statement.close();connection.close();}
}
分析一下:
2.2.3步驟:
1.注冊驅動DriverManager
2.用戶信息(用戶名、密碼)和url
url:
"jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&&useSSL=true"
格式:協議://主機地址:端口號/數據庫名?參數1&參數2
3.獲取數據庫驅動對象,connection代表數據庫,那就擁有數據的權利,(數據庫設置自動提交
事務提交、事務回滾)
Connection connection = DriverManager.getConnection(url, username, password);connection.commit();connection.rollback();connection.setAutoCommit(true);
4.具體sql執行類,上面我們有了數據庫需要對于表進行操作還需要一個執行sql語句的類對象
Statement statement = connection.createStatement();
然后就使用sql語句對其進行增刪改查
Statement statement = connection.createStatement();statement.execute(); // 執行任何sql語句statement.executeUpdate(); //更新、插入、刪除都是這個,顯示的結果是受到影響的行數statement.executeQuery(); //查詢操作返回的ResultSet
=======================================================================
3.JDBC的抽取
根據上面我們可以知道對于驅動和連接,以及釋放資源都是固定,我們需要進行改變的就是statement對其進行增刪改查(CURD),因此我們需要對其進行提取工具類以及重點介紹一下statement的操作!!!
3.1.首先我想對于文件的,我想避免耦合,因此我想寫一個配置文件對其進行提取(寫在一個.properties文件)
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&&useSSL=true username=root password=123456
3.2.上面是完成了一些文件的修改,我還行進一步簡化就是我想創建一個工具類JDBCUnity
package com.xcl.test.Utils;import java.io.FileReader;
import java.sql.*;
import java.util.Properties;public class JdbcUtils {private static String driver = null;private static String url = null;private static String username = null;private static String password = null;//創建一個靜態代碼塊,在工具類之前就就加載好了static {try {//1.propertise集合類Properties properties = new Properties();//加載這個文件properties.load(new FileReader("D:\\javaLearn\\JDBC\\src\\dataBase.properties"));//開始獲取文件里面的內容driver = properties.getProperty("driver");url = properties.getProperty("url");username = properties.getProperty("username");password = properties.getProperty("password");//然后就開始體現工具類里面的東西Class.forName("driver");} catch (Exception e) {e.printStackTrace();}}//獲取連接public static Connection getConnection() throws SQLException {return DriverManager.getConnection(url, username, password);}//釋放資源public static void close(Statement statement,Connection connection){//釋放資源if (statement!=null){try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection!=null){try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}public static void close(ResultSet resultSet,Statement statement,Connection connection){//釋放資源if (resultSet!=null){try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (statement!=null){try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection!=null){try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}
}
3.3.那么我就簡單進行測試一下(進行增刪改查)
package com.xcl.test;import com.xcl.test.Utils.JdbcUtils;import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;public class Demo02 {public static void main(String[] args) {Connection connection = null;Statement statement = null;ResultSet results = null;try {//獲得連接connection = JdbcUtils.getConnection();//常見sql對象statement = connection.createStatement();//開始增刪改查//添加
// String sqlAdd = "insert into student value ('12', '張三', '123456', '男', '1999-01-01', '北京', '123456@qq.com')";
// int i = statement.executeUpdate(sqlAdd);
// if (i > 0){
// System.out.println("添加成功");
// }//刪除
// String sqlDelete = "delete from student where id = '12'";
// int i = statement.executeUpdate(sqlDelete);
// if (i > 0){
// System.out.println("刪除成功");
// }//修改
// String sqlUpdate = "update student set name = '李四' where id = '11'";
// int i = statement.executeUpdate(sqlUpdate);
// if (i > 0){
// System.out.println("修改成功");
// }
//
// //查詢String sqlQuery = "select * from student";results = statement.executeQuery(sqlQuery);while (results.next()){System.out.print("id=" + results.getObject("id"));System.out.print("name=" + results.getObject("name"));System.out.print("password=" + results.getObject("password"));System.out.print("sex=" + results.getObject("sex"));System.out.print("birthday=" + results.getObject("birthday"));System.out.print("address=" + results.getObject("address"));System.out.print("email=" + results.getObject("email"));System.out.println();}} catch (SQLException e) {throw new RuntimeException(e);}finally {JdbcUtils.close(statement,connection);}}
}
4.SQL注入
SQL存在漏洞,會被攻擊導致數據泄露。SQL會被拼接or,使得你查詢語句where判斷一直變成true,就可以盜取!!!
package com.xcl.test;import com.xcl.test.Utils.JdbcUtils;import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;public class SQLError {//SQL注入public static void main(String[] args) {login("' or '1=1","' or '1=1");
// login("趙六","123456");}private static void login(String userName,String password) {Connection connection = null;Statement statement = null;ResultSet results = null;try {//獲得連接connection = JdbcUtils.getConnection();//常見sql對象statement = connection.createStatement();//查詢String sqlQuery = "select * from student where name='"+userName+"' and password='"+password+"'";results = statement.executeQuery(sqlQuery);while (results.next()){System.out.print("id=" + results.getObject("id"));System.out.print("name=" + results.getObject("name"));System.out.print("password=" + results.getObject("password"));System.out.print("sex=" + results.getObject("sex"));System.out.print("birthday=" + results.getObject("birthday"));System.out.print("address=" + results.getObject("address"));System.out.print("email=" + results.getObject("email"));System.out.println();}} catch (SQLException e) {throw new RuntimeException(e);}finally {JdbcUtils.close(statement,connection);}}
}
因此我們就需要更好的對象去先預處理這個東西
(主要就是進行預編譯,里面輸入的參數還用?先先代替就行)
步驟:
1.先用問號代替
2.然后進行填充
代碼展示:
package com.xcl.test;import com.xcl.test.Utils.JdbcUtils;import java.sql.*;public class SQLError {//SQL注入public static void main(String[] args) {
// login("' or '1=1","' or '1=1");login("趙六","123456");}private static void login(String userName,String password) {Connection connection = null;Statement statement = null;ResultSet results = null;try {//獲得連接connection = JdbcUtils.getConnection();//常見sql對象
// statement = connection.createStatement();//查詢String sqlQuery = "select * from student where name= ? and password= ?";PreparedStatement preparedStatement = connection.prepareStatement(sqlQuery);preparedStatement.setString(1,userName);preparedStatement.setString(2,password);results = preparedStatement.executeQuery();while (results.next()){System.out.print("id=" + results.getObject("id"));System.out.print("name=" + results.getObject("name"));System.out.print("password=" + results.getObject("password"));System.out.print("sex=" + results.getObject("sex"));System.out.print("birthday=" + results.getObject("birthday"));System.out.print("address=" + results.getObject("address"));System.out.print("email=" + results.getObject("email"));System.out.println();}} catch (SQLException e) {throw new RuntimeException(e);}finally {JdbcUtils.close(statement,connection);}}
}
5.事務(在java里面表現事務)【這不是完整代碼,里面還有工具類和數據庫,只是給大家一個思路!】
package com.xcl.test;import com.xcl.test.Utils.JdbcUtils;import java.sql.*;public class TransactionDemo {public static void main(String[] args) {Connection con = null;PreparedStatement ps = null;ResultSet resultSet = null;try {//連接con = JdbcUtils.getConnection();//關閉自動提交,之后不需要開啟因為會自動開啟事務con.setAutoCommit(false);//進行轉賬的修改String sql_A = "update account set money = money - 200 where name = 'A'";ps = con.prepareStatement(sql_A);ps.executeUpdate();String sql_B = "update account set money = money + 200 where name = 'B'";ps = con.prepareStatement(sql_B);ps.executeUpdate();//提交事務con.commit();System.out.println("轉賬成功!");} catch (SQLException e) {//失敗后進行回滾try {con.rollback();} catch (SQLException ex) {throw new RuntimeException(ex);}throw new RuntimeException(e);}finally {JdbcUtils.close(resultSet,ps,con);}}
}