本來以為寫過一個使用python與數據庫連接的文章,但是今天突然發現沒有,那就直接寫Java與數據庫連接的吧。當然如果大家有需要可以告訴我,有時間的話也可以寫一個的pymysql的使用的。
數據庫有很多種,接下來我就以MySQL為例來進行講解了,當然Java與其他數據庫的連接也同樣是這幾步,因為他們都有同一個接口,見下
一.注冊驅動
就是確定要使用哪個數據庫
1.1下載驅動包
如果有對應jar包的就可以跳過這一步了
對應的地址在這里:MySQL驅動包下載地址
當然一般不建議使用最新版,舊版可以在Archives中找到
下載完成之后,解壓
1.2添加jar包
打開解壓過的文件,并找到上面標注的jar包
1.一般是可以直接放到你Java項目中的lib目錄里面(如果找不到可以直接進行下面的第二步)
2.還需要在開發工具里把該 JAR 包添加到項目的類路徑,這樣 Java 虛擬機運行時才能找到它。
接下來需要在項目結構的模塊中添加對應的jar包
直接在文件中找到之前你解壓完成后,文件里對應的jar包就好了
1.3編寫代碼
// 1.注冊驅動(確定要使用哪個數據庫)
Class.forName("com.mysql.jdbc.Driver"); // 加載Driver類--在mysql5的驅動包之后,其實也可以省略// DriverManager.registerDriver(new com.mysql.jdbc.Driver()); 也可以這樣,但是會有點顯得多此一舉(會重復注冊兩次)
二.連接數據庫
就是要獲取到一個數據庫連接對象
// 2.連接數據庫(獲取到一個數據庫連接對象)
final String URL = "jdbc:mysql://127.0.0.1:3306/demo1"; // :前可看作協議,數據庫不同,協議不同
final String NAME = "root"; // 你數據庫的用戶名
final String PASSWORD = "1234"; // 你數據庫的密碼Connection conn = DriverManager.getConnection(URL, NAME, PASSWORD);
其實Connection與MySQL的事務也有關系,在這里我也就不過多贅述了,如果想繼續擴充可以自己去查找資料,或在評論區滴我,后續有需要的我可以補充上噢
三.編寫sql語句
一般建議先保證語句正確之后,再直接復制到代碼中
這個也就不多說了,舉個栗子
// 3.編寫sql語句
String sql = "select * from tb_user;";
四.把sql語句發送給數據庫
4.1實踐
數據庫執行sql代碼,并返回執行結果
// 4.把sql語句發送給數據庫(數據庫執行sql代碼,并返回執行結果)
Statement stmt = conn.createStatement(); // 基于數據庫連接對象,創建一個操作數據庫的對象// ①使用sql查找時
ResultSet rs = stmt.executeQuery(sql); // 把sql代碼發給數據庫// ②使用sql進行增刪改操作時
int row = stmt.executeUpdate(sql); // 執行DML,DDL語句
// 執行DML語句時,執行后返回受影響行數 受影響行數為0表示增刪改沒有成功
// 執行DDL語句時,執行后返回0表示成功
4.2sql注入風險
但是使用Statement會有sql注入風險
例如,如果在上一步的password是這樣的:
// 3.編寫sql語句
String username = "aaa";
String password = "aaa' or 1=1-- ";// sql語句拼接時記得加空格(這里的?表示一個占位符)
String sql = "select * from tb_user where username = ? and password = ?;";
那么在使用Statement執行結果時,是一定會成功的,這時候對于數據庫中的數據來說,就不是很安全了,所以在這個時候就有了PreparedStatement。而他其實也是Statement的一個子接口。
// 4.把sql語句發送給數據庫(數據庫執行sql代碼,并返回執行結果)
// 創建預編譯對象PreparedStatement pstmt = conn.prepareStatement(sql); // 基于數據庫連接對象,創建一個操作數據庫的對象// 給sql語句中的占位符賦值
pstmt.setString(1,username);
pstmt.setString(2,password);ResultSet rs = pstmt.executeQuery(); // 這里就不需要再傳遞內容了
其實PreparedStatement的作用也就相當于把敏感字符進行了一個轉義,像'和--都把他們變成了字符串,而不是sql語句本身
一般來說建議使用:PreparedStatement,防止出錯
五.處理sql的執行結果
注意區分查找和增刪改其他操作的書寫。
// 5.處理sql的執行結果(查詢)
while(rs.next()){System.out.print(rs.getInt("id")+"\t");System.out.print(rs.getString("username")+"\t");System.out.println(rs.getString("password")+"\t");
}// 如果是增刪改操作,就可以直接判斷受影響的行數是多少來判斷是否執行成功了
if(row > 0){System.out.println("數據操作成功");
}else{System.out.println("數據操作失敗");
}
使用步驟:
1.游標向下移動一行,并判斷該行是由有數據:next()
2.獲取數據:getxxx(參數)
要注意,
1.獲取到的數據是什么,就是get什么,例如說int-getInt,varchar-getString
2.而getxxx里面的參數,不管他之前的名字是什么,結果集上是什么就用什么來查詢
因為在idea中返回的結果,是根據mysql中的執行結果來返回的
六.釋放資源
斷開和數據庫的連接
// 6.釋放資源(斷開和數據庫的連接)
rs.close();
stmt.close(); // 注意是pstmt還是stmt
conn.close();
就把所有打開的都關閉就是了,誰和誰的都不一樣,關閉的順序與你書寫的順序相反
就像我下面整體的代碼,開啟連接的順序是:conn,stmt,rs。所以關閉的順序就是rs,stmt,conn。
總:代碼示例
下面代碼我都是使用了@Test注解,大家也可以直接修改為main函數
基礎代碼:
package JDBC;import org.junit.Test;import java.sql.*;public class JbdcQuickStart {@Testpublic void quickStartTest() throws ClassNotFoundException, SQLException {
// 1.注冊驅動(確定要使用哪個數據庫)Class.forName("com.mysql.jdbc.Driver"); // 加載Driver類--在mysql5的驅動包之后,其實也可以省略
// DriverManager.registerDriver(new com.mysql.jdbc.Driver()); 也可以這樣,但是會有點顯得多此一舉(會重復注冊兩次)// 2.連接數據庫(獲取到一個數據庫連接對象)String url = "jdbc:mysql://127.0.0.1:3306/demo1"; // :前可看作協議Connection conn = DriverManager.getConnection(url,"root","1234");// 3.編寫sql語句String sql = "select * from tb_user;";// 4.把sql語句發送給數據庫(數據庫執行sql代碼,并返回執行結果)Statement stmt = conn.createStatement(); // 基于數據庫連接對象,創建一個操作數據庫的對象ResultSet rs = stmt.executeQuery(sql); // 把sql代碼發給數據庫
// 5.處理sql的執行結果while(rs.next()){System.out.print(rs.getInt("id")+"\t");System.out.print(rs.getString("username")+"\t");System.out.println(rs.getString("password")+"\t");}// 6.釋放資源(斷開和數據庫的連接)rs.close();stmt.close();conn.close();}
}
防止sql注入代碼:
?
package JDBC;import org.junit.Test;import java.sql.*;public class SQL注入demo {// 使用PerparedStatement解決SQL注入問題@Testpublic void loginTest() throws ClassNotFoundException, SQLException {// 1.注冊驅動(確定要使用哪個數據庫)Class.forName("com.mysql.jdbc.Driver");// 2.連接數據庫(獲取到一個數據庫連接對象)final String URL = "jdbc:mysql://127.0.0.1:3306/demo1";final String NAME = "root";final String PASSWORD = "1234";Connection conn = DriverManager.getConnection(URL, NAME, PASSWORD);// 3.編寫sql語句String username = "aaa";String password = "aaa' or 1=1-- ";// sql語句拼接時記得加空格
// String sql = "select * from tb_user "+"where username = '小花' and password = '12345';";String sql = "select * from tb_user where username = ? and password = ?;";// 4.把sql語句發送給數據庫(數據庫執行sql代碼,并返回執行結果)
// 創建預編譯對象PreparedStatement pstmt = conn.prepareStatement(sql); // 基于數據庫連接對象,創建一個操作數據庫的對象// 給sql語句中的占位符賦值pstmt.setString(1,username);pstmt.setString(2,password);ResultSet rs = pstmt.executeQuery(); // 這里就不需要再傳遞內容了
// 5.處理sql的執行結果if (rs.next()) {String strname = rs.getString("username");String pwd = rs.getString("password");System.out.println("歡迎" + username + "登錄");} else {System.out.println("登錄失敗!");}// 6.釋放資源(斷開和數據庫的連接)rs.close();pstmt.close();conn.close();}
}
附加
其實我們對比代碼可以發現,不管是什么操作,有幾個步驟其實是不會改變的
這時候我們就可以把相似的代碼合成一個包,以方便我們調用
接下來就直接給代碼了
package JDBC.JDBC工具類的使用;/** 編寫工具類:* 1.私有構造方法* 2.提供靜態方法* */import java.sql.*;public class JdbcUtil {private static final String DRIVER = "com.mysql.jdbc.Driver";// 數據庫連接參數(這是固定上了,按理說我感覺可以讓他到時候自己設置)private static final String URL = "jdbc:mysql://127.0.0.1:3306/demo1";private static final String NAME = "root";private static final String PASSWORD = "1234";
// private static final String URL = "";
// private static final String NAME = "";
// private static final String PASSWORD = "";// 注冊驅動(僅需1次)static {try {Class.forName(DRIVER);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}// 數據庫連接public static Connection getConnection() throws SQLException {return DriverManager.getConnection(URL, NAME, PASSWORD);}// 釋放資源(重載)public static void close(Connection conn, Statement stmt) {close(conn,stmt,null); // 方法重用}public static void close(Connection conn, Statement stmt, ResultSet rs) {try {if (rs != null) {rs.close();}} catch (SQLException e) {throw new RuntimeException(e);}try {if (stmt != null) {stmt.close();}} catch (SQLException e) {throw new RuntimeException(e);}try {if (conn != null) {conn.close();}} catch (SQLException e) {throw new RuntimeException(e);}}
}
總體就是這樣啦,如果有什么問題可以隨時在評論區提問噢~~~