MySQL數據庫與JDBC編程

MySQL數據庫與JDBC編程

JDBC (Java Database Connectivity)

對於關係數據庫而言,最基本的數據存儲單元是數據表

SQL:Structured Query Language,結構化查詢語言。

DDL(Data Definition Language,數據定義語言)語句

主要操作數據庫對象。

創建表

CREATE TABLE [模式名.] 表名
(
	columnName1 datatype [default expr],
  ...
)

利用子查詢建表

CREATE TABLE [模式名.] 表名 [col[, col]]
as
select * from user_inf;

修改表結構

增加列定義
ALTER TABLE 表名
add
(
	columnName1 datatype [default expr],
  ...
);

字符串值由單引號引起。

修改列定義
ALTER TABLE 表名
modify columnName datatype [default expr] [first|afterColName];

firstafterColName指定需要將目標修改到指定位置。

刪除列
ALTER TABLE 表名
drop columnName;
刪除數據表
DROP TABLE 表名;

表結構刪除,表對象不再存在;表的所有數據被刪除;該表所有相關的索引、約束也被刪除。

清空表
TRUNCATE 表名;

刪除表內的全部數據,但保留表結構。

MySQL重命名數據表
ALTER TABLE 表名 rename to 新表名;
MySQL修改列名
ALTER TABLE 表名 CHANGE 列名 新列名 type [default expr] [first|afterColName]

數據庫約束

5種完整性約束

1、NOT NULL:非空約束,指定某列不能爲空。

CREATE TABLE 表名 (id int NOT NULL);

2、UNIQUE:唯一約束,指定某列或者某幾列組合不能重複。

1、列級約束
name VARCHAR(255) UNIQUE;

2、表級約束(爲多列組合建立唯一約束,或想自行指定約束名)
CREATE TABLE 表名(
# 表級約束語法建立唯一約束
  UNIQUE (name),
# 並指定約束名
  CONSTRAINT 新約束名 UNIQUE(pass),
# 指定兩列組合不允許重複
  CONSTRAINT 新約束名 UNIQUE(name, pass)
)

3、MySQL刪除約束
ALTER TABLE 表名 DROP INDEX 約束名;

4、大部分數據庫刪除約束
ALTER TABLE 表名 DROP CONSTRAINT 約束名;

3、PRIMARY KEY:主鍵,指定該列的值可以唯一地標識該條記錄。

1、列級約束
CREATE TABLE 表名 (id INT PRIMARY KEY);

2、表級約束
CREATE TABLE 表名 (
  id INT,
	CONSTRAINT 約束名 PRIMARY KEY(id)
);

3、建立多列組合的主鍵約束
CREATE TABLE 表名 (
  id INT,
	name VARCHAR(255),
	PRIMARY KEY(id, name)
);

4、刪除主鍵約束
ALTER TABLE 表名 DROP PRIMARY KEY;

5、增加主鍵約束
MODIFY:採用列級約束語法
ADD:採用表級約束語法

6、主鍵自增長
id INT AUTO_INCREMENT PRIMARY KEY

4、FOREIGN KEY:外鍵,指定該行記錄從屬於主表中的一條記錄,主要用於保證一個或兩個數據表之間的參照完整性。

1、指定兩列的聯合外鍵
CREATE TABLE 表名(
	Sname	VARCHAR(255),
  Spass VARCHAR(255),
  CONSTRAINT 約束名 FOREIGN KEY(Sname, Spass) REFERENCES 主表名(Fname, Fpass)
 );
 
 
2、級聯刪除(定義當刪除主表記錄時,從表記錄也會隨之級聯刪除/從表記錄的外鍵設置爲null)
CREATE TABLE 表名(
  Sname VARCHAR(255),
	FOREIGN KEY(Sname) REFERENCES 主表名(Fid) ON DELETE CASCADE # 也可用ON DELETE SET NULL 
);

5、CHECK:檢查,制定一個布爾表達式,用於指定對應列的值必須滿足該表達式。(MySQL不支持)

CREATE TABLE 表名(
  key INT,
	CHECK(key>10)
);

索引(一個數據庫對象)

創建索引的唯一作用是加速對錶的查詢,索引通過使用快速路徑訪問方法來快速定位數據,從而減少了磁盤的I/0。

創建索引:

1、自動
當在表上定義主鍵約束、唯一約束、外鍵約束時,系統自動創建對應的索引。
2、手動
CREATE INDEX 索引名 ON 表名(name, pass);

刪除索引:

1、自動
數據表被刪除時,該表上的索引自動被刪除。
2、手動
DROP INDEX 索引名 ON 表名;

視圖

數據表中數據的邏輯顯示。

創建視圖,且不允許修改數據:

CREATE OR REPLACE VIEW 視圖名 AS 查詢語句 WITH CHECK OPTION;

刪除視圖

DROP VIEW 視圖名;

DML(Data Definition Language,數據定義語言)語句

主要操作數據表裏的數據。由insert intoupdatedelete from三個命令組成。

insert into語句

向數據表中插入記錄:

INSERT INTO 表名 (id, name, age) VALUES(1, "sxf", null);

帶子查詢的插入(要求所選的數據列個數相等、類型匹配):

INSERT INTO 表名 (name) SELECT name FROM2;

MySQL多條插入

INSERT INTO 表名 (id, name) VALUES(1, "a"), (2,"b");

update語句

修改數據表的記錄。

UPDATE 表名 SET name="sxf", pass="123" WHERE id=1;

delete from語句

刪除指定數據表的記錄。總是整行刪除。

DELETE FROM 表名 WHERE id>1 AND id<5;

單表查詢

字符串連接用:concat();爲數據列和表達式起別名用:as或空格;爲表起別名用:as或空格;去除重複行用:distinct;

SELECT DISTINCT CONCAT("na", "me") AS myName FROM table t WHERE id*2>4;

where後的其他運算符

1、expr2<=expr1<=expr3
expr1 BETWEEN expr2 AND expr3;

2、expr1等於括號裏的任意一個表達式的值
expr1 IN(expr2, expr3, ...);

3、字符串匹配,下劃線代表一個字符,百分號代表任意多個字符
like ‘_%;

4、是否爲null
is null;

order by輸出排序

desc降序,默認asc升序。如果按多列排序,則每列的asc、desc必須單獨設定。

SELECT * FROM table ORDER BY name DESC, id ASC;

數據庫函數

多用在select和where後面。

MySQL單行函數

選出字符長度
SELECT char_length(ip) FROM IP;

計算sin值
SELECT sin(1.57);

爲日期添加一定時間
SELECT ADDDATE('1998-01-02', 3);

獲取當前日期
SELECT CURDATE();

獲取當前時間
SELECT curtime();

如果expr1=null,返回expr2,否則返回expr1
ifnull(expr1, expr2)

如果expr1=expr2,返回null,否則返回expr1
nullif(expr1, expr2)

類似於三目運算符“:?”
if(expr1, expr2, expr3)

如果expr1爲null,返回true,否則返回false
isnull(expr1)

選擇流程控制
CASE value
WHEN value1 THEN result1
WHEN value2 THEN result2
...
ELSE result
END

CASE 
WHEN condition1 THEN result1
WHEN condition2 THEN result2
...
ELSE result
END

分組和組函數

將一組記錄作爲整體計算,返回一個結果。

計算多行expr的平均值,數據類型必須是數值型。distinct不計算重複值;默認all計算重複值
avg([distinct|all] expr)

計算多行expr的總條數,數據類型可以是任意類型。*表示統計該表內的記錄行數;distinct不計算重複值
count({*|[distinct|all] expr})

計算多行expr的最大值
max(expr)

計算多行expr的最小值
min(expr)

計算多行expr的綜合
sum([distinct|all] expr)
group by分組

對記錄進行顯示分組。

相同的記錄當成一組,並過濾組having
SELECT * FROM ip GROUP BY ip HAVING count(*)>2;

多列的值完全相同時纔會被當成一組
SELECT count(*) FROM ip GROUP BY id, ip;

多表連接查詢

交叉連接

無需任何連接條件。

SELECT s.*, name FROM studentTable s CROSS JOIN teacherTable t;

自然連接

以兩個表中的同名列作爲連接條件;若沒有同名列,則效果等同交叉連接

SELECT s.*, name FROM studentTable s NATURAL JOIN teacherTable t;

using子句連接

顯式指定兩個表中的哪些同名列作爲連接條件,要求必須有同名列;自然連接無法指定

SELECT s.*, name FROM studentTable s JOIN teacherTable t USING(id);

on子句連接

每個on子句只能指定一個連接條件。如果需要進行N表連接,則需要N-1個join…on對。

SELECT s.*, name FROM studentTable s JOIN teacherTable t ON s.teacher=t.id;

左、右、全外連接

分別使用left[outer]join、right[outer]join、full[outer]join,連接條件通過on子句指定。

  • 左外連接:把左邊表中所有不滿足連接條件的記錄全部列出。
  • 右外連接:把右邊表中所有不滿足連接條件的記錄全部列出。
  • 全外連接(MySQL不支持):把兩個表中所有不滿足連接條件的記錄全部列出。
SELECT s.*, name FROM studentTable s LEFT JOIN teacherTable t ON s.teacher=t.id;

子查詢

在查詢語句中嵌套另一個查詢,支持多層嵌套。

  • 出現在from語句後當成數據表;
  • 出現在where條件後作爲過濾條件的值;
  • 子查詢要用括號括起來;
  • 把子查詢當成數據表時,可以爲該子查詢起別名。
SELECT * FROM (SELECT * FROM ip) t WHERE t.id>1;

SELECT * FROM ip WHERE id>(SELECT Sid FROM Stable WHERE Sname='SXF');

集合運算

  • 兩個結果集所包含的數據列的數量必須相等。
  • 兩個結果集所包含的數據列的數據類型也必須一一對應。

union並運算

SELECT 語句 UNION SELECT 語句;

minus差運算

MySQL不支持,使用not in代替。

SELECT 語句 MINUS SELECT 語句;

SELECT XX FROM XX WHERE (XX, XX) NOT IN (XX, XX);

intersect交運算

MySQL不支持,使用join…on代替。

SELECT 語句 INTERSECT SELECT 語句;

SELECT XX FROM XX JOIN XX ON (XX=XX) WHERE XX=XX;

JDBC的經典用法

JDBC編程步驟

Java 連接 MySQL 需要驅動包,最新版下載地址爲:http://dev.mysql.com/downloads/connector/j/,解壓後得到 jar 庫文件,然後在對應的項目中導入該庫文件。

1、加載數據庫驅動

通常使用Class類的forName()靜態方法來加載驅動。

Class.forName("com.mysql.ch.hdbc.Driver");
Class.forName("oracle.jdbc.driver.OracleDriver");

2、通過DriverManager獲取數據庫連接

DriverManager.getConnection("jdbc:mysql://hostname:port/databasename", "user", "pwd");

3、通過Connection對象創建Statement對象

  • createStatement():創建基本的Statement對象;
  • prepareStatement(String sql):根據傳入的SQL語句創建預編譯的Statement對象;
  • prepareCall(String sql):根據傳入的SQL語句創建CallableStatement對象;

4、使用Statement執行SQL語句

  • execute():可以執行任何SQL語句,但比較麻煩;
  • executeUpdate():主要用於執行DML和DDL語句。執行DML語句返回受SQL語句影響的行數,執行DDL語句返回0;
  • executeQuery():只能執行查詢語句,執行後返回代表查詢結果的ResultSet對象;

5、操作結果集

  • next()、previous()、first()、last()、beforeFirst()、afterLast()、absolute()等移動記錄指針的方法;
  • getXxx()方法獲取指針指向行、特定列的值。既可以使用列索引作爲參數,也可使用列名作爲參數。

6、回收數據庫資源

示例:簡單SQL查詢

package com.sxf.sql;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class Main {
    public static void main(String[] args) throws Exception{
	    // 1、加載驅動,使用反射知識。
        Class.forName("com.mysql.cj.jdbc.Driver");
        try {
            // 2、使用DriverManager獲取數據庫連接。
            Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/tz_music?useSSL=false&serverTimezone=UTC",
                    "root", "1061700625");
            // 3、使用Connection創建Statement對象。
            Statement state = conn.createStatement();
            // 4、執行SQL語句。
            //   execute:可執行任何SQL語句,返回一個boolean值
            //   executeQuery:執行查詢語句,返回一個結果集
            //   executeUpdate:執行DML語句,返回一個整數
            ResultSet res = state.executeQuery("select * from tz_music;");
            // 5、獲取數據。
            //   next:將記錄指針下移一行,若有效則返回true
            //   getXxx:通過列名或列索引獲取記錄指針
            while (res.next()){
                System.out.println(res.getString("music_name"));
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

執行SQL語句的方法

使用executeLargeUpdate方法執行DDL和DML語句

示例:讀取ini文件,連接並創建數據表

; mysql.ini文件
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/tz_music?useSSL=false&serverTimezone=UTC
user=root
pwd=1061700625
package com.sxf.sql;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;


class Sql{
    private String driver;
    private String url;
    private String user;
    private String pwd;
    public void initParam(String paramFile) throws Exception{
        var props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pwd = props.getProperty("pwd");
    }

    public void createTable(String sql) throws Exception{
        Class.forName(driver);
        try (
            Connection conn = DriverManager.getConnection(url, user, pwd);
            Statement state = conn.createStatement();
            )
        {
            state.executeUpdate(sql);
        }
    }
}

public class Main {
    public static void main(String[] args) throws Exception{
        Sql sql = new Sql();
        sql.initParam("mysql.ini");
        sql.createTable("create table jdbc(id int primary key, name varchar(255));");
        System.out.println("OK");
    }
}

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-wfh2YzCv-1590568160482)(C:\Users\SXF\AppData\Roaming\Typora\typora-user-images\image-20200525151944809.png)]

使用PreparedStatement執行SQL語句

PreparedStatement的好處與作用:

  • 預編譯SQL語句,性能更好;
  • 無需“拼接”SQL語句,編程更簡單;
  • 可以防止SQL注入,安全性更好。

示例:使用PreparedStatement插入記錄

class Sql
{
  ... ...
	public void insertTable() throws Exception{
        Class.forName(driver);
        try (
                Connection conn = DriverManager.getConnection(url, user, pwd);
                PreparedStatement state = conn.prepareStatement("insert into jdbc values(?, ?);");
            )
        {
            state.setInt(1, 1);
            state.setString(2, "a");
            state.executeUpdate();
            state.setInt(1, 2);
            state.setString(2, "a");
            state.executeUpdate();
        }
    }
}

public class Main {
    public static void main(String[] args) throws Exception{
        Sql sql = new Sql();
        sql.initParam("mysql.ini");
        sql.insertTable();
        System.out.println("OK");
    }
}

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-EN8mEgxf-1590568160485)(C:\Users\SXF\AppData\Roaming\Typora\typora-user-images\image-20200525154002693.png)]

使用CallableStatement調用存儲過程

調用存儲過程的SQL語句格式:{call 過程名(? ,?, ?..)},其中的問號作爲存儲過程參數的佔位符。

存儲過程的參數既有傳入參數,也有傳出參數。

  • 傳入參數:通過setXxx()方法爲傳入參數設置值。
  • 傳出參數:調用registerOutParameter()方法註冊該參數;通過getXxx()方法獲取指定傳出參數的值。

示例:調用存儲功能

public void callProc() {
  try {
    Class.forName(driver);
    Connection conn= DriverManager.getConnection(url, user, pwd);
    CallableStatement cstmt = conn.prepareCall("{call add_pro(?, ?, ?)}");
    cstmt.setInt(1, 4);
    cstmt.setInt(2, 5);
    // 註冊第三個參數是int類型的輸出參數
    cstmt.registerOutParameter(3, Types.INTEGER);
    cstmt.execute();
    System.out.println(cstmt.getInt(3));
  }catch (Exception e){
    e.printStackTrace();
  }
}

管理結果集

可滾動、可更改的結果集

可滾動:可以使用方法自由移動記錄指針的ResultSet。

可更新:可調用ResultSet的方法來修改記錄指針所指記錄、特定列的值。

示例:創建可滾動、可更改的結果集

public void query(String sql) throws Exception
{
  Class.forName(driver);
  try (
    Connection conn = DriverManager.getConnection(url, user, pwd);
    // 傳入控制結果集可滾動、可更新的參數
    PreparedStatement state = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
    ResultSet res = state.executeQuery();
  )
  {
    res.last();
    int rowCount = res.getRow();
    for (int i = rowCount; i >0; i--) {
      res.absolute(i);
      System.out.println(res.getString(1)+" - "+res.getString(2));
      res.updateString(2, "abc");
      res.updateRow();
    }
  }
}

sql.query("select * from jdbc");

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-JEnHurJ1-1590568160487)(C:\Users\SXF\AppData\Roaming\Typora\typora-user-images\image-20200526175750855.png)]

處理Blob類型數據

  1. Blob(Binary Long Object)二進制長對象,用於存儲大文件,典型的Blob內容是一張圖片或一個聲音文件。

  2. Blob數據插入數據庫需要使用PreparedStatement,該對象有一個方法:setBinaryStream(int index, InputStream x),該方法可以爲指定參數傳入二進制輸入流,從而可以實現將Blob數據保存到數據庫中。

  3. 調用ResultSet的**getBlob(int index)**方法可以從ResultSet裏取出Blob數據,該方法返回一個Blob對象。

  4. Blob對象提供了**getBinaryStream()方法來獲取該Blob數據的輸入流,也可以使用Blob對象提供的getBytes()**方法直接取出該Blob對象封裝的二進制數據。

  5. 建立數據表時,創建一個mediumblob類型的數據列,用於保存圖片數據。

  6. MySQL裏數據庫裏的blob類型最多隻能存儲64KB內容,而mediumblob類型可以存儲16MB的內容。

示例:通過SQL的Blob存儲並讀取圖片數據

public void blobDemo(String fileName) throws Exception
{
  Connection conn;
  PreparedStatement state;
  PreparedStatement query;
  Class.forName(driver);
  try {
    conn = DriverManager.getConnection(url, user, pwd);
    state = conn.prepareStatement("insert into jdbc values (?,?,?)", Statement.RETURN_GENERATED_KEYS);
    query = conn.prepareStatement("select image from jdbc");
    String imageName = fileName.substring(fileName.lastIndexOf('\\')+1, fileName.lastIndexOf('.'));
    var f = new File(fileName);
    var is = new FileInputStream(f);
    state.setObject(1, 8);
    state.setObject(2, "img");
    state.setBinaryStream(3, is, (int)f.length());
    int affect = state.executeUpdate();
    System.out.println(affect);
    ResultSet res = query.executeQuery();
    if(res.next()){
      Blob imgBlob = res.getBlob(3);
      var out = imgBlob.getBinaryStream();
    }
  }catch (Exception e){
    e.printStackTrace();
  }
}

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-kpyagRVy-1590568160489)(C:\Users\SXF\AppData\Roaming\Typora\typora-user-images\image-20200526213528489.png)]

使用ResultSetMetaData分析結果集

描述其他數據的數據,用以獲取關於ResultSet的描述信息。通過**getMetaData()**方法獲得ResultSetMetaData對象。需要一定的系統開銷。

三個常用方法:

  • int getColumnCount():返回改ResultSet的列數量
  • String getColumnName(int column):返回指定索引的列名
  • int getColumnType(int column):返回指定索引的列類型

示例:分析結果集

public void metaData() throws Exception
{
  Class.forName(driver);
  Connection conn = DriverManager.getConnection(url, user, pwd);
  Statement state = conn.createStatement();
  ResultSet set = state.executeQuery("select * from jdbc");
  ResultSetMetaData rsmd = set.getMetaData();
  System.out.println(rsmd.getColumnCount());
  System.out.println(rsmd.getColumnName(2));
  System.out.println(rsmd.getColumnType(2));
}

使用RowSet包裝結果集

RowSet接口下包含jdbcRowSet、CachedRowSet、FilteredRowSet、JoinRowSet、WebRowSet常用子接口。

jdbcRowSet需要保持與數據庫的連接;其餘4個是離線的RowSet,無需保持連接。

RowSetFactory和RowSet

RowSet常用方法:

setUrl(String url)、setUsername(String name)、setPassword(String pwd)、setCommand(String sql)、execute()

示例:通過RowSetFactory使用jdbcRowSet

public void update(String sql) throws Exception
{
  Class.forName(driver);
  // 創建RowSetFactory
  RowSetFactory factory = RowSetProvider.newFactory();
  // 創建實例
  JdbcRowSet jdbcRs = factory.createJdbcRowSet();
  // 設置連接信息
  jdbcRs.setUrl(url);
  jdbcRs.setUsername(user);
  jdbcRs.setPassword(pwd);
  jdbcRs.setCommand(sql);
  // 執行查詢
  jdbcRs.execute();
  jdbcRs.afterLast();
  // 向前滾動結果集
  while (jdbcRs.previous()){
    System.out.println(jdbcRs.getString(1));
    // 修改記錄行
    jdbcRs.updateString(2, "123");
    // 提交修改
    jdbcRs.updateRow();
  }
}

離線RowSet

直接將底層數據讀入內存中,封裝成RowSet對象,而RowSet對象完全可以當成Java Bean來使用。

示例:CachedRowSet離線操作SQL

public void query(String sql) throws Exception
{
  Class.forName(driver);
  // 獲取數據庫連接
  Connection conn = DriverManager.getConnection(url, user, pwd);
  Statement stmt = conn.createStatement();
  ResultSet res = stmt.executeQuery(sql);
  // 創建RowSetFactory
  RowSetFactory factory = RowSetProvider.newFactory();
  // 創建實例
  CachedRowSet cachedRs = factory.createCachedRowSet();
  // 裝填RowSet
  cachedRs.populate(res);
  // 關閉資源
  res.close();
  stmt.close();
  conn.close();

  cachedRs.afterLast();
  // 重新獲取數據庫連接
  Connection conn2 = DriverManager.getConnection(url, user, pwd);
  conn2.setAutoCommit(false);
  // 把對RowSet所做的修改同步到底層數據庫
  cachedRs.acceptChanges(conn2);
}

事務處理

事務的概念

事務ACID特性:原子性atomicity、一致性consistency、隔離性isolation、持續性durability

事務提交:

  • 顯示提交:使用commit
  • 自動提交:執行DDL或DCL語句,或程序正常退出

事務回滾:

  • 顯式回滾:使用rollback
  • 自動回滾:系統錯誤,或強行退出

普通的提交、回滾都會結束當前事務,但回滾到指定中間點因爲依然處於事務之中,所以不會結束當前事務。

JDBC事務支持

調動Connection的**setAutoCommit()**方法來關閉自動提交,開啓事務。

當Connection遇到一個未處理的SQLException異常時,系統將會非正常退出,事務也會自動回滾。但如果程序捕獲了該異常,則需要再異常處理塊中顯式地回滾事務。

// 關閉自動提交,開啓事務
conn.setAutoCommit(false);
// 提交事務
conn.commit();
// 回滾事務
conn.rollback();
// 創建保存點
point = conn.setSavePoint();
// 回滾到保存點
conn.rollback(point);

使用批量更新

  1. 多條SQL語句將被作爲一批操作被同時收集,同時提交。
  2. 使用批量更新也需要先創建一個Statement對象,然後利用該對象的addBatch()方法將多條SQL語句同時收集起來,最後調用Statement對象的executeLargeBatch()或executeBatch()方法同時執行這些SQL語句。
  3. 如果在批量更新的addBatch()方法中添加select查詢語句,程序將直接出現錯誤。
  4. 爲了讓批量操作可以正確地處理錯誤,必須把批量執行的操作視爲單個事務,如果批量更新在執行過程中失敗,則讓事務回滾到批量操作開始之前的狀態。薇樂大道這種效果,程序應該在開始批量操作之前先關閉自動提交,然後開始收集更新語句,當批量操作執行結束後,提交事務,並恢復之前的自動提交模式。
Statement stmt = conn.createStatement();
stmt.addBatch(sql1);
stmt.addBatch(sql2);
stmt.addBatch(sql3);
... ...
stmt.executeLargeBatch();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章