在操做數據庫時,update操做會返回數據庫更新行數,可是在JDBC默認狀況下則不會返回數據庫更新行數,這一點有所不一樣,在實際操做中可能會出現意想不到的結果。在使用ORM框架時,例如Mybatis、Hibernate時因爲其底層一樣使用JDBC API,因此一樣會出現上訴問題。java
首先,咱們看一下JDBC API中是對update操做返回值得定義,主要涉及要Statement.executeUpdate()和PreparedStatement.executeUpdate()兩個操做,其返回值定義同樣:mysql
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。sql
咱們來編寫幾個例子,實際來看看JDBC Update的返回值。注:這裏使用的是Mysq數據庫進行測試:數據庫
JDBC Connection Properties:api
driver=com.mysql.jdbc.Driver url=jdbc:mysql://120.55.59.65:3306/study_jdbc?characterEncoding=utf8 username=root password=********
JDBC DDL:oracle
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: 1url
JDBC正確的Update操做,注意這裏,咱們重複執行2次:code
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經過建立PreparedStatement時指定返回主鍵,而後經過getGenerateKeys()方法進行查詢返回主鍵。注:這裏主鍵必須是Auto Increment
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生成主鍵的方式比較特別,因此上面的方式並不適用於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); }