1. 程式人生 > >JDBC Update操作返回值和Insert操作返回主鍵

JDBC Update操作返回值和Insert操作返回主鍵

not null rest enc 不同 生成 statement -a AC ret

JDBC Update操作返回值

在操作數據庫時,update操作會返回數據庫更新行數,但是在JDBC默認情況下則不會返回數據庫更新行數,這一點有所不同,在實際操作中可能會出現意想不到的結果。在使用ORM框架時,例如Mybatis、Hibernate時由於其底層同樣使用JDBC API,所以同樣會出現上訴問題。

JDBC API

首先,我們看一下JDBC API中是對update操作返回值得定義,主要涉及要Statement.executeUpdate()和PreparedStatement.executeUpdate()兩個操作,其返回值定義一樣:

either (1) the row count for
SQL Data Manipulation Language (DML) statements or (2) 0 for SQL statements that return nothing

也就是說DDL語句返回值為0,而DML語句返回值只是說返回Row Count,而沒有說返回Affect Count。

JDBC Update操作的幾個例子

我們來編寫幾個例子,實際來看看JDBC Update的返回值。註:這裏使用的是Mysq數據庫進行測試:

JDBC Connection Properties:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://120.55.59.65:3306/study_jdbc?characterEncoding=utf8
username=root
password=********

JDBC DDL:

Connection connection = DriverUtils.getConnection();
String sql1 = "DROP TABLE IF EXISTS `update_return_value`;";
String Sql2 = " CREATE TABLE `update_return_value`"
    + "(`id` bigint(20) PRIMARY KEY NOT NULL AUTO_INCREMENT, `name` varchar(255))"
    + "ENGINE=InnoDB AUTO_INCREMENT=1;";
PreparedStatement preparedStatement = connection.prepareStatement
(sql1); preparedStatement.executeUpdate(); PreparedStatement statement = connection.prepareStatement(Sql2); int updateValue = statement.executeUpdate(); System.out.println("Update Return Value: " + updateValue);

控制臺輸出:Update Return Value: 0

JDBC Insert:

Connection connection = DriverUtils.getConnection();
String sql = "INSERT INTO update_return_value(name) VALUES (?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, "2222");
int updateValue = preparedStatement.executeUpdate();
System.out.println("Update Return Value: " + updateValue);

控制臺輸出:Update Return Value: 1

JDBC正確的Update操作,註意這裏,我們重復執行2次:

Connection connection = DriverUtils.getConnection();
String sql = "UPDATE update_return_value SET name = ? WHERE id = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, "11111");
preparedStatement.setLong(2, 1L);
int updateValue = preparedStatement.executeUpdate();
System.out.println("Update Return Value: " + updateValue);

控制臺輸出:Update Return Value: 1 /n Update Return Value: 1

JDBC不正確的Update操作:

Connection connection = DriverUtils.getConnection();
String sql = "UPDATE update_return_value SET name = ? WHERE id = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, "11111");
preparedStatement.setLong(2, 2L);
int updateValue = preparedStatement.executeUpdate();
System.out.println("Update Return Value: " + updateValue);

控制臺輸出:Update Return Value: 0

從上面我們可以看出,出乎意料的是在正確update更新操作執行2次結果都是1,如果是返回值是行影響數目則第二次應該為0,因為第二次更新時數據庫並沒有變化。然後我們把JDBC Properties中的url變為一下,然後重新執行就會出現第二次更新返回值為0

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://120.55.59.65:3306/study_jdbc?characterEncoding=utf8&useAffectedRows=true
username=root
password=*********

總結

JDBC Update操作DML語句默認情況下返回Rows-Matches數目,而不是Rows-Affect數目,可以在url中加入userAffectedRows=true 則會返回Rows-Affect數目

JDBC Insert操作返回主鍵

JDBC通過創建PreparedStatement時指定返回主鍵,然後通過getGenerateKeys()方法進行查詢返回主鍵。註:這裏主鍵必須是Auto Increment

大多數數據庫返回主鍵方式,例如Mysql

Connection connection = DriverUtils.getConnection();
String sql = "INSERT INTO insert_return_key(name) VALUES (?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
preparedStatement.setString(1, "3333");
preparedStatement.executeUpdate();
ResultSet generatedKeys = preparedStatement.getGeneratedKeys();
while (generatedKeys.next()) {
    long generateKey = generatedKeys.getLong(1);
}

Oracle方式返回主鍵,當然也可以用於mysql等數據庫

由於Oracle生成主鍵的方式比較特別,所以上面的方式並不適用於Oracle

Connection connection = DriverUtils.getConnection();
String sql = "INSERT INTO insert_return_key(name) VALUES (?)";
String[] keysName = {"id"};
PreparedStatement preparedStatement = connection.prepareStatement(sql, keysName);
preparedStatement.setString(1, "3333");
preparedStatement.executeUpdate();
ResultSet generatedKeys = preparedStatement.getGeneratedKeys();
while (generatedKeys.next()) {
      long generateKey = generatedKeys.getLong(1);
}

JDBC Update操作返回值和Insert操作返回主鍵