目錄
一、JDBC開(kāi)發(fā)步驟
1.Java程序連接數(shù)據(jù)庫(kù)
1.1引入MySQL驅(qū)動(dòng)包
1.2Java連接MySQL步驟
2 實(shí)現(xiàn)增刪改查操作
2.1 添加數(shù)據(jù)
2.2 修改數(shù)據(jù)
2.3 刪除數(shù)據(jù)
2.4 查詢數(shù)據(jù)
二、JDBC處理相關(guān)問(wèn)題
1 解決SQL注入問(wèn)題
1.1、問(wèn)題演示
1.2、解決問(wèn)題
2 JDBC事務(wù)處理
3 獲取自增長(zhǎng)鍵值
4 批處理操作
一、JDBC開(kāi)發(fā)步驟
1.Java程序連接數(shù)據(jù)庫(kù)
1.1引入MySQL驅(qū)動(dòng)包
使用Java連接MySQL之前需要先引入MySQL驅(qū)動(dòng)jar包。
創(chuàng)建Java項(xiàng)目,并引入MySQL驅(qū)動(dòng)jar包到項(xiàng)目中,如下圖示例:
?
1.2Java連接MySQL步驟
A、代碼示例:
//注冊(cè)驅(qū)動(dòng):把驅(qū)動(dòng)類(lèi)加載到內(nèi)存中
//注意:5.1版本驅(qū)動(dòng)包中驅(qū)動(dòng)類(lèi)名:com.mysql.jdbc.Driver
//8.0版本驅(qū)動(dòng)類(lèi)名:com.mysql.cj.jdbc.Driver
Class.forName("com.mysql.cj.jdbc.Driver");
//與數(shù)據(jù)庫(kù)建立連接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/atguigu","root","1234");
//實(shí)現(xiàn)增刪改查數(shù)據(jù)
//.....
//關(guān)閉連接:如果不再使用連接需要斷開(kāi)連接以釋放資源(底層是TCP/IP協(xié)議和IO流操作)
conn.close();
//程序能正常編譯執(zhí)行表示連接成功,如果拋異常表示連接失敗。
B、步驟說(shuō)明:
-
注冊(cè)驅(qū)動(dòng)
此步驟的目的是把驅(qū)動(dòng)類(lèi)加載到內(nèi)存中,可以通過(guò)以下方式實(shí)現(xiàn):
//方式一:不推薦,因會(huì)導(dǎo)致注冊(cè)驅(qū)動(dòng)被執(zhí)行兩次(看源碼),并且代碼強(qiáng)依賴數(shù)據(jù)庫(kù)驅(qū)動(dòng)jar DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver()); //方式二:創(chuàng)建了兩個(gè)Driver對(duì)象(見(jiàn)源碼),并且強(qiáng)依賴數(shù)據(jù)庫(kù)驅(qū)動(dòng) new com.mysql.cj.jdbc.Driver(); //方式三:推薦,反射方式,接收字符串參數(shù),降低了對(duì)驅(qū)動(dòng)類(lèi)的依賴 Class.forName("com.mysql.cj.jdbc.Driver");
實(shí)際在JDK6之后
DriverManager
就已經(jīng)可以實(shí)現(xiàn)自動(dòng)注冊(cè)驅(qū)動(dòng),如果手動(dòng)注冊(cè)了驅(qū)動(dòng),不再自動(dòng)注冊(cè)。但是仍然建議顯示通過(guò)反射方式注冊(cè)驅(qū)動(dòng)。需要驅(qū)動(dòng)包中此位置文件
META-INF/services/java.sql.Driver
中包含內(nèi)容:com.mysql.cj.jdbc.Driver
-
與數(shù)據(jù)庫(kù)建立連接
加載驅(qū)動(dòng)程序后,可以使用DriverManager的重載方法
getConnection
創(chuàng)建Connection對(duì)象,每個(gè)Connection對(duì)象表示Java程序與數(shù)據(jù)庫(kù)之間的一個(gè)物理連接。Connection conn = getConnection(String url,String user,String password);
其中不同數(shù)據(jù)庫(kù)URL配置不同:
RDBMS | JDBC驅(qū)動(dòng)程序名稱 | URL格式 |
---|---|---|
MySQL | com.mysql.cj.jdbc.Driver |
jdbc:mysql://hostname / databaseName |
ORACLE | oracle.jdbc.driver.OracleDriver |
jdbc:oracle:thin:@ hostname:port Number:databaseName |
DB2 | com.ibm.db2.jdbc.net.DB2Driver |
jdbc:db2:hostname:port Number / databaseName |
URL格式說(shuō)明:
協(xié)議:子協(xié)議://主機(jī)名:端口/數(shù)據(jù)庫(kù)名?參數(shù)名1=參數(shù)值1&參數(shù)名2=參數(shù)值2 其中,如果主機(jī)是本機(jī)或端口是默認(rèn)3306端口時(shí),可以缺省。如:jdbc:mysql:///databaseName
示例:jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=utf8(如果JDBC程序與服務(wù)器端的字符集不一致,會(huì)導(dǎo)致亂碼,那么可以通過(guò)參數(shù)指定服務(wù)器端的字符集)
使用某些版本驅(qū)動(dòng)包,建立連接時(shí)可能還需要設(shè)置服務(wù)器時(shí)區(qū)參數(shù):
jdbc:mysql://localhost:3306/dbname?serverTimezone=Asia/Shanghai
三個(gè)重載方法創(chuàng)建連接示例:
//方式一:
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testJDBC?user=root&password=1234");
//方式二:
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "1234");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testJDBC",info);
//方式三:(推薦方式)
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testJDBC","root","1234");
2 實(shí)現(xiàn)增刪改查操作
2.1 添加數(shù)據(jù)
/*
用JDBC實(shí)現(xiàn)添加一條記錄到atguigu數(shù)據(jù)庫(kù)的t_department表中。
mysql> desc t_department;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| did | int | NO | PRI | NULL | auto_increment |
| dname | varchar(20) | NO | UNI | NULL | |
| description | varchar(200) | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
mysql> select * from t_department;
+-----+--------+------------------+
| did | dname | description |
+-----+--------+------------------+
| 1 | 研發(fā)部 | 負(fù)責(zé)研發(fā)工作 |
| 2 | 人事部 | 負(fù)責(zé)人事管理工作 |
| 3 | 市場(chǎng)部 | 負(fù)責(zé)市場(chǎng)推廣工作 |
| 4 | 財(cái)務(wù)部 | 負(fù)責(zé)財(cái)務(wù)管理工作 |
| 5 | 后勤部 | 負(fù)責(zé)后勤保障工作 |
| 6 | 測(cè)試部 | 負(fù)責(zé)測(cè)試工作 |
+-----+--------+------------------+
6 rows in set (0.00 sec)
步驟:
1、注冊(cè)驅(qū)動(dòng)
2、獲取數(shù)據(jù)庫(kù)連接
3、獲取Statement對(duì)象,用來(lái)執(zhí)行sql
4、執(zhí)行sql,即執(zhí)行Statement對(duì)象的方法:int executeUpdate(),(增刪改操作時(shí))
5、釋放資源
*/
public class TestInsert {
public static void main(String[] args)throws Exception {
//1.注冊(cè)驅(qū)動(dòng),把驅(qū)動(dòng)類(lèi)加載到內(nèi)存中
Class.forName("com.mysql.cj.jdbc.Driver");
//2.創(chuàng)建數(shù)據(jù)庫(kù)連接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/atguigu","root","1234");
//3.獲取StateMent
String sql = "insert into t_department values(null,'數(shù)據(jù)部門(mén)','數(shù)據(jù)部門(mén)簡(jiǎn)介')";
PreparedStatement pst = conn.prepareStatement(sql);
//4.執(zhí)行SQL,插入數(shù)據(jù),返回sql影響的記錄數(shù)
int len = pst.executeUpdate();
System.out.println(len>0 ? "添加成功" : "添加失敗");
//5.釋放資源
pst.close();
conn.close();
/*
mysql> select * from t_department;
+-----+--------------+------------------+
| did | dname | description |
+-----+--------------+------------------+
| 1 | 研發(fā)部 | 負(fù)責(zé)研發(fā)工作 |
| 2 | 人事部 | 負(fù)責(zé)人事管理工作 |
| 3 | 市場(chǎng)部 | 負(fù)責(zé)市場(chǎng)推廣工作 |
| 4 | 財(cái)務(wù)部 | 負(fù)責(zé)財(cái)務(wù)管理工作 |
| 5 | 后勤部 | 負(fù)責(zé)后勤保障工作 |
| 6 | 測(cè)試部 | 負(fù)責(zé)測(cè)試工作 |
| 7 | 數(shù)據(jù)部門(mén) | 數(shù)據(jù)部門(mén)簡(jiǎn)介 |
+-----+--------------+------------------+
7 rows in set (0.00 sec)
*/
}
}
2.2 修改數(shù)據(jù)
public class TestUpdate {
public static void main(String[] args)throws Exception {
//1.把驅(qū)動(dòng)類(lèi)加載到內(nèi)存中
Class.forName("com.mysql.cj.jdbc.Driver");
//2.獲取數(shù)據(jù)庫(kù)連接對(duì)象
String url = "jdbc:mysql://localhost:3306/atguigu";
Connection conn = DriverManager.getConnection(url, "root", "1234");
//3.獲取Statement對(duì)象
String sql = "update t_department set description = 'xx' where did = 7";
PreparedStatement pst = conn.prepareStatement(sql);
//4.執(zhí)行SQL,修改數(shù)據(jù), 返回sql影響的記錄數(shù)
int len = pst.executeUpdate();
System.out.println(len > 0 ? "修改成功" : "修改失敗");
//5.釋放資源
pst.close();
conn.close();
}
}
/*
mysql> select * from t_department;
+-----+--------------+------------------+
| did | dname | description |
+-----+--------------+------------------+
| 1 | 研發(fā)部 | 負(fù)責(zé)研發(fā)工作 |
| 2 | 人事部 | 負(fù)責(zé)人事管理工作 |
| 3 | 市場(chǎng)部 | 負(fù)責(zé)市場(chǎng)推廣工作 |
| 4 | 財(cái)務(wù)部 | 負(fù)責(zé)財(cái)務(wù)管理工作 |
| 5 | 后勤部 | 負(fù)責(zé)后勤保障工作 |
| 6 | 測(cè)試部 | 負(fù)責(zé)測(cè)試工作 |
| 7 | 測(cè)試數(shù)據(jù)部門(mén) | xx |
+-----+--------------+------------------+
7 rows in set (0.00 sec)
*/
2.3 刪除數(shù)據(jù)
public class TestDelete {
public static void main(String[] args)throws Exception {
//1.把驅(qū)動(dòng)類(lèi)加載到內(nèi)存中
Class.forName("com.mysql.cj.jdbc.Driver");
//2.獲取數(shù)據(jù)庫(kù)連接對(duì)象
String url = "jdbc:mysql://localhost:3306/atguigu";
Connection conn = DriverManager.getConnection(url, "root", "1234");
//3.獲取Statement對(duì)象
String sql = "delete from t_department where did = 7";
PreparedStatement pst = conn.prepareStatement(sql);
//4.執(zhí)行SQL,刪除數(shù)據(jù), 返回sql影響的記錄數(shù)
int len = pst.executeUpdate();
System.out.println(len > 0 ? "刪除成功" : "刪除失敗");
//5.釋放資源
pst.close();
conn.close();
}
}
/*
mysql> select * from t_department;
+-----+--------+------------------+
| did | dname | description |
+-----+--------+------------------+
| 1 | 研發(fā)部 | 負(fù)責(zé)研發(fā)工作 |
| 2 | 人事部 | 負(fù)責(zé)人事管理工作 |
| 3 | 市場(chǎng)部 | 負(fù)責(zé)市場(chǎng)推廣工作 |
| 4 | 財(cái)務(wù)部 | 負(fù)責(zé)財(cái)務(wù)管理工作 |
| 5 | 后勤部 | 負(fù)責(zé)后勤保障工作 |
| 6 | 測(cè)試部 | 負(fù)責(zé)測(cè)試工作 |
+-----+--------+------------------+
6 rows in set (0.00 sec)
*/
2.4 查詢數(shù)據(jù)
/*
步驟:
1、注冊(cè)驅(qū)動(dòng)
2、獲取數(shù)據(jù)庫(kù)連接
3、獲取Statement對(duì)象,用來(lái)執(zhí)行sql
4、執(zhí)行sql,即執(zhí)行Statement對(duì)象的方法:
(1)int executeUpdate():執(zhí)行insert,update,delete等更新數(shù)據(jù)庫(kù)數(shù)據(jù)的sql
(2)ResultSet executeQuery():執(zhí)行select查詢的sql,返回一個(gè)結(jié)果集
(3)boolean execute():可以用來(lái)執(zhí)行DDL語(yǔ)句
5、遍歷結(jié)果集ResultSet:
boolean next():判斷是否還有下一行
getObject(字段名或序號(hào)),getString(字段名或序號(hào)),getInt(字段名或序號(hào))等
6、釋放資源
*/
public class TestSelect {
public static void main(String[] args)throws Exception {
//1.注冊(cè)驅(qū)動(dòng),把驅(qū)動(dòng)類(lèi)加載到內(nèi)存中
Class.forName("com.mysql.cj.jdbc.Driver");
//2.獲取數(shù)據(jù)庫(kù)連接對(duì)象
String url = "jdbc:mysql://localhost:3306/atguigu";
Connection conn = DriverManager.getConnection(url, "root", "1234");
//3.獲取Statement對(duì)象
String sql = "select * from t_department";
PreparedStatement pst = connn.prepareStatement(sql);
//4.執(zhí)行查詢SQL,返回查詢結(jié)果
ResultSet resultSet = pst.executeQuery();
//5.遍歷結(jié)果集
while(rs.next()){ //while循環(huán)一次,迭代一行,遍歷一行
int did = rs.getInt("did");//get一次得到一個(gè)單元格的數(shù)據(jù)
String dname = rs.getString("dname");
String decription = rs.getString("description");
System.out.println(did +"\t" + dname +"\t" + decription);
}
//釋放資源
rs.close();
pst.close();
conn.close();
}
}
二、JDBC處理相關(guān)問(wèn)題
1 解決SQL注入問(wèn)題
PrepareStatement接口是Statement的子接口,提供了更優(yōu)秀的功能
返回值 | 方法名 | 含義 |
---|---|---|
ResultSet | executeQuery() | 執(zhí)行預(yù)處理sql語(yǔ)句的查詢操作 |
int | executeUpdate() | 執(zhí)行預(yù)處理sql語(yǔ)句的增刪改操作 |
void | setInt(int parameterIndex, int x) | 設(shè)置sql參數(shù) |
void | setFloat(int parameterIndex, float x) | 設(shè)置sql參數(shù) |
void | setString(int parameterIndex, String x) | 設(shè)置sql參數(shù) |
void | setDate(int parameterIndex, java.sql.Date x) | 設(shè)置sql參數(shù) |
void | setObject(int parameterIndex, Object x) | 設(shè)置sql參數(shù) |
... | ... | ... |
1.1、問(wèn)題演示
(1)SQL語(yǔ)句拼接
//提取用戶名和密碼變量,模擬登錄操作
String name = "tom";
String password = "123456";
String sql =
"select * from users where name='" + name + "' and password='" + password + "'";
System.out.println("sql="+sql);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
(2)SQL注入 ?
String name = "tom";
String password="' or '1'='1";// 如果登錄時(shí)鍵盤(pán)錄入密碼為' or '1'='1時(shí),結(jié)果登錄成功
String sql =
"select * from users where name='" + name + "' and password='" + password + "'";
System.out.println("sql="+sql);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
(3)處理blob等類(lèi)型的數(shù)據(jù)
-
如果數(shù)據(jù)庫(kù)表中字段定義是blob類(lèi)型時(shí),需要寫(xiě)入的是二進(jìn)制數(shù)據(jù),即需要通過(guò)字節(jié)流寫(xiě)入二進(jìn)制數(shù)據(jù),這時(shí)無(wú)法把數(shù)據(jù)直接拼接成sql字符串。
1.2、解決問(wèn)題
(1)避免sql拼接
String sql = "insert into users(name,password,email,birthday) values(?,?,?,?)";
PreparedStatement pst = conn.prepareStatement(sql);//這里要傳帶?的sql,然后mysql端就會(huì)對(duì)這個(gè)sql進(jìn)行預(yù)編譯
//設(shè)置?的具體值
/*pst.setString(1, name);
pst.setString(2, password);
pst.setString(3, email);
pst.setDouble(4, birthday);*/
pst.setObject(1, name);
pst.setObject(2, password);
pst.setObject(3, email);
pst.setObject(4, birthday);
int len = pst.executeUpdate();//此處不能傳sql
System.out.println(len);
(2)不會(huì)有sql注入問(wèn)題
//即使輸入' or '1'= '1也沒(méi)問(wèn)題
String sql = "select * from users where name=? and password=?";
String name = "tom";
String password = "123123";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1,name );
pstmt.setString(2,password );
ResultSet rs = pstmt.executeQuery();
(3)處理blob類(lèi)型的數(shù)據(jù) ?
//pic字段為blob類(lèi)型
String sql = "insert into users(name,pic) value(?,?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1,"tom" );
pstmt.setBlob(2,new FileInputStream("D:/1.jpeg"));
int i = pstmt.executeUpdate();
System.out.println(i > 0 ? "成功" : "失敗");
注意兩個(gè)問(wèn)題:
①my.ini關(guān)于上傳的字節(jié)流文件有大小限制,可以在my.ini中修改變量max_allowed_packet值
max_allowed_packet=16M
②每一種blob有各自大小限制:
tinyblob:255字節(jié)、blob:65k、mediumblob:16M、longblob:4G文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-484933.html
2 JDBC事務(wù)處理
?采用轉(zhuǎn)賬案例文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-484933.html
/*
* mysql默認(rèn)每一個(gè)連接是自動(dòng)提交事務(wù)的。
* 那么當(dāng)我們?cè)贘DBC這段,如果有多條語(yǔ)句想要組成一個(gè)事務(wù)一起執(zhí)行的話,那么在JDBC這邊怎么設(shè)置手動(dòng)提交事務(wù)呢?
* (1)在執(zhí)行之前,設(shè)置手動(dòng)提交事務(wù)
* Connection的對(duì)象.setAutoCommit(false)
* (2)成功:
* Connection的對(duì)象.commit();
* 失?。? * Connection的對(duì)象.rollback();
*
* 補(bǔ)充說(shuō)明:
* 為了大家養(yǎng)成要的習(xí)慣,在關(guān)閉Connection的對(duì)象之前,把連接對(duì)象設(shè)置回自動(dòng)提交
* (3)Connection的對(duì)象.setAutoCommit(true)
*
* 因?yàn)槲覀儸F(xiàn)在的連接是建立新的連接,那么如果沒(méi)有還原為自動(dòng)提交,沒(méi)有影響。
* 但是我們后面實(shí)際開(kāi)發(fā)中,每次獲取的連接,不一定是新的連接,而是從連接池中獲取的舊的連接,而且你關(guān)閉也不是真關(guān)閉,
* 而是還給連接池,供別人接著用。以防別人拿到后,以為是自動(dòng)提交的,而沒(méi)有commit,最終數(shù)據(jù)沒(méi)有成功。
*/
public class TestTransaction {
public static void main(String[] args) throws Exception{
/*
* 一般涉及到事務(wù)處理的話,那么業(yè)務(wù)邏輯都會(huì)比較復(fù)雜。
* 例如:購(gòu)物車(chē)結(jié)算時(shí):
* (1)在訂單表中添加一條記錄
* (2)在訂單明細(xì)表中添加多條訂單明細(xì)的記錄(表示該訂單買(mǎi)了什么東西)
* (3)修改商品表的銷(xiāo)量和庫(kù)存量
* ...
* 那么我們今天為了大家關(guān)注事務(wù)的操作,而不會(huì)因?yàn)閺?fù)雜的業(yè)務(wù)邏輯的影響導(dǎo)致我們的理解,那么我們這里故意
* 用兩條修改語(yǔ)句來(lái)模擬組成一個(gè)簡(jiǎn)單的事務(wù)。
* update t_department set description = 'xx' where did = 2;
* update t_department set description = 'yy' where did = 3;
*
* 我希望這兩條語(yǔ)句要么一起成功,要么一起回滾
* 為了制造失敗,我故意把第二條語(yǔ)句寫(xiě)錯(cuò)
* update t_department set description = 'yy' (少了where) did = 3;
*/
//1、注冊(cè)驅(qū)動(dòng)
Class.forName("com.mysql.cj.jdbc.Driver");
//2、獲取連接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "1234");
//設(shè)置手動(dòng)提交事務(wù)
conn.setAutoCommit(false);
//3、執(zhí)行sql
String sql1 = "update t_department set description = 'xx' where did = 2";
String sql2 = "update t_department set description = 'yy' did = 3";//這句錯(cuò)的
//使用prepareStatement的sql也可以不帶問(wèn)號(hào)?
PreparedStatement pst = null;
try {
pst = conn.prepareStatement(sql1);
int len = pst.executeUpdate();
System.out.println("第一條:" + (len>0?"成功":"失敗"));
pst = conn.prepareStatement(sql2);
len = pst.executeUpdate();
System.out.println("第二條:" + (len>0?"成功":"失敗"));
//都成功了,就提交事務(wù)
System.out.println("提交");
conn.commit();
} catch (Exception e) {
System.out.println("回滾");
//失敗要回滾
conn.rollback();
}
//4、關(guān)閉
pst.close();
conn.setAutoCommit(true);//還原為自動(dòng)提交
conn.close();
}
}
3 獲取自增長(zhǎng)鍵值
/*
* 我們通過(guò)JDBC往數(shù)據(jù)庫(kù)的表格中添加一條記錄,其中有一個(gè)字段是自增的,那么在JDBC這邊怎么在添加之后直接獲取到這個(gè)自增的值
* PreparedStatement是Statement的子接口。
* Statement接口中有一些常量值:
* (1)Statement.RETURN_GENERATED_KEYS
*
* 要先添加后獲取到自增的key值:
* (1)PreparedStatement pst = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
* (2)添加sql執(zhí)行完成后,通過(guò)PreparedStatement的對(duì)象調(diào)用getGeneratedKeys()方法來(lái)獲取自增長(zhǎng)鍵值,遍歷結(jié)果集
* ResultSet rs = pst.getGeneratedKeys();
*/
public class TestAutoIncrement {
public static void main(String[] args) throws Exception{
//1、注冊(cè)驅(qū)動(dòng)
Class.forName("com.mysql.cj.jdbc.Driver");
//2、獲取連接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123456");
//3、執(zhí)行sql
String sql = "insert into t_department values(null,?,?)";
/*
* 這里在創(chuàng)建PreparedStatement對(duì)象時(shí),傳入第二個(gè)參數(shù)的作用,就是告知服務(wù)器端
* 當(dāng)執(zhí)行完sql后,把自增的key值返回來(lái)。
*/
PreparedStatement pst = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
//設(shè)置?的值
pst.setObject(1, "測(cè)試部");
pst.setObject(2, "測(cè)試項(xiàng)目數(shù)據(jù)");
//執(zhí)行sql
int len = pst.executeUpdate();//返回影響的記錄數(shù)
if(len>0){
//從pst中獲取到服務(wù)器端返回的鍵值
ResultSet rs = pst.getGeneratedKeys();
//因?yàn)檫@里的key值可能多個(gè),因?yàn)閕nsert語(yǔ)句可以同時(shí)添加多行,所以用ResultSet封裝
//這里因?yàn)橹惶砑右粭l,所以用if判斷
if(rs.next()){
Object key = rs.getObject(1);
System.out.println("自增的key值did =" + key);
}
}
//4、關(guān)閉
pst.close();
conn.close();
}
}
4 批處理操作
/*
* 批處理:
* 批量處理sql
*
* 例如:
* (1)訂單明細(xì)表的多條記錄的添加
* (2)批量添加模擬數(shù)據(jù)
* ...
*
* 不用批處理,和用批處理有什么不同?
* 批處理的效率很多
*
* 如何進(jìn)行批處理操作?
* (1)在url中要加一個(gè)參數(shù)
* rewriteBatchedStatements=true,默認(rèn)值false會(huì)發(fā)送多次sql請(qǐng)求
* 那么我們的url就變成了 jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
* 這里的?,表示?后面是客戶端給服務(wù)器端傳的參數(shù),多個(gè)參數(shù)直接使用&分割
* (2)調(diào)用方法不同
* pst.addBatch();
* int[] all = pst.executeBatch();
*
* 注意:如果批量添加時(shí),insert使用values,不要使用value,否則相當(dāng)于發(fā)送多次sql執(zhí)行
*/
public class TestBatch {
public static void main(String[] args) throws Exception{
long start = System.currentTimeMillis();
//例如:在部門(mén)表t_department中添加1000條模擬數(shù)據(jù)
//1、注冊(cè)驅(qū)動(dòng)
Class.forName("com.mysql.cj.jdbc.Driver");
//2、獲取連接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true", "root", "123456");
//3、執(zhí)行sql
String sql = "insert into t_department values(null,?,?)";
PreparedStatement pst = conn.prepareStatement(sql);
//設(shè)置?的值
for (int i = 1; i <=1000; i++) {
pst.setObject(1, "模擬部門(mén)"+i);
pst.setObject(2, "模擬部門(mén)的簡(jiǎn)介"+i);
pst.addBatch();//添加到批處理一組操作中,攢一塊處理
/* if(i % 500 == 0){//有時(shí)候也攢一部分,執(zhí)行一部分
//2.執(zhí)行
pst.executeBatch();
//3.清空
pst.clearBatch();
}*/
}
//執(zhí)行批處理操作
pst.executeBatch();
//4、關(guān)閉
pst.close();
conn.close();
long end = System.currentTimeMillis();
System.out.println("耗時(shí):" + (end - start));//耗時(shí):821
}
}
到了這里,關(guān)于Java-JDBC連接數(shù)據(jù)庫(kù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!