1、public int update(String tableName, Map<String, Object> mapRecord, String where) throws SQLException//根據條件更新單條記錄
2、public int update(String tableName, Map<String, Object> mapRecord) throws SQLException//更新單條記錄
3、public int update(String tableName, List<Map> listRecord) throws SQLException //更新多條記錄,主鍵值不變
4、public int update(String tableName, List<Map> listRecord, String where) throws SQLException //根據where條件,更新多條記錄,主鍵值不變
它們都調用底層最核心的方法
private int _preparedStatementUpdate(String tableName, List<Map> listRecord, boolean isUpdateKey, String whereStr) throws SQLException
將使用參數Map變量或者是List<Map>變量更新數據庫表中的記錄,待更新的記錄的條件是主鍵值等於mapRecord.get(主鍵名),在這一組操作中,主鍵值不變。
底層核心方法_preparedStatementUpdate同__preparedStatementInsert的共同點有以下幾點:
1、插入語句或更新語句只需要合成一次;
2、都支持相同的SQL數據類型及其對應的Java類;
3、都需要實現相同的通配符對應的賦值方法(參見“SQL數據類型與Java類的對應關係”一文);
4、都整合相同的異常,統一拋出SQLException異常。
底層核心方法_preparedStatementUpdate同__preparedStatementInsert的區別在於:
1、合成PreparedStatement的更新語句;
2、更新數據時,保持主鍵值不變。
合成PreparedStatement的更新語句的算法是:
Map<String, Object> _m = new LinkedHashMap(listRecord.get(0));//獲取一條記錄,作爲過濾、分組依據
String[] tableFields = db.getFields(tableName);//表中的字段
String[] tableKeys = db.getKeys(tableName);//表中的主鍵
Object[] recordFields = (_m.keySet()).toArray(); //獲取記錄裏的字段名的集合
for (int i = 0; i < recordFields.length; i++) {
if (!tool.isInFields(tableFields, recordFields[i].toString())) {
_m.remove(recordFields[i].toString());//移除無效字段, 查看記錄中的字段在表中是否存在,如果不存在,則移除到
}
}
Object[] k0 = (_m.keySet()).toArray(); //過濾後的有效字段
Map<String, Object> key_m = new LinkedHashMap();//記錄裏的主鍵
if (!isUpdateKey) {
for (int i = 0; i < k0.length; i++) {
if (tool.isInFields(tableKeys, k0[i].toString())) {//記錄中是否有主鍵
key_m.put(k0[i].toString(), _m.remove(k0[i].toString()));//將記錄中的主鍵移到key_m中;保證不對主鍵更新
}
}
}
Object[] fields = (_m.keySet()).toArray(); //記錄中不包含主鍵的有效字段;再次過濾掉主鍵字段的結果
Object[] keys = (key_m.keySet()).toArray(); //記錄中包含的主鍵
if (isUpdateKey) {
if (keys.length == 0 || keys.length != tableKeys.length) {
return num;
}
}
String[] kss = new String[fields.length]; //保存"鍵名=?"
for (int i = 0; i < fields.length; i++) {
kss[i] = fields[i].toString() + "=?";
}
String n_v = tool.arryToString(kss, ",");
String preparedStatementUpdate = "update " + tableName + " set " + n_v + " ";
//System.out.println(preparedStatementUpdate);
完整的_preparedStatementUpdate代碼
/**
* 使用PreparedStatement更新多條記錄 本方法是根據JDBC API類名的判斷來存貯數據<br/>
* 爲了方便表單數據的錄入,本方法提供了用字符串來表達Integer|Long|Short|Float|Double|Bigdecimal|java.sql.Date等常規類型的支持,<br/>
* 但請注意:用字符串表達Date時,目前java.sql.Date僅支持將"yyyy-mm-dd"格式轉換成Date對象;<br/>
* 對於其它類型,用戶必須建立相應類型的對象; 本方法提供了對上傳文件的支持; 零長度字符串將保存爲null。<br/>
* 詳細的數據類型,可參閱《Java開發者年鑑》p700 PreparedStatement的setXXX方法<br/>
*
*
* 完成更新的步驟: 1、過濾記錄中無效字段,得有效字段Object[] fields<br/>
* 2、根據isUpdateKey對有效字段繼續分組:!true時,再得主鍵字段組Object[] keys和非主鍵字段組Object[]
* fields<br/> 3、自動生成PreparedStatement所需的更新操作<br/> 4、迭代記錄for (Map record :
* listRecord) {}<br/> 5、執行PreparedStatement的executeUpdate(updateSQL);<br/>
*
*
* @param tableName 是一個表名
* @param listRecord 是具有相同結構的一組記錄
* @param isUpdateKey 是否更新主鍵
* @param whereStr
* 是操作條件,插入時不起作用,更新時,若where==null||"".equals(where),則自動根據記錄自身主鍵字段的鍵值對組合where條件語句
* 是從LinkedHashMap參數中獲取的值
* @throws SQLException
*/
private int _preparedStatementUpdate(String tableName, List<Map> listRecord, boolean isUpdateKey, String whereStr) throws SQLException {
int num = 0;
if (listRecord == null || listRecord.isEmpty()) {
return num;
}
Map<String, Object> _m = new LinkedHashMap(listRecord.get(0));//獲取一條記錄,作爲過濾、分組依據
String[] tableFields = db.getFields(tableName);//表中的字段
String[] tableKeys = db.getKeys(tableName);//表中的主鍵
Object[] recordFields = (_m.keySet()).toArray(); //獲取記錄裏的字段名的集合
for (int i = 0; i < recordFields.length; i++) {
if (!tool.isInFields(tableFields, recordFields[i].toString())) {
_m.remove(recordFields[i].toString());//移除無效字段, 查看記錄中的字段在表中是否存在,如果不存在,則移除到
}
}
Object[] k0 = (_m.keySet()).toArray(); //過濾後的有效字段
Map<String, Object> key_m = new LinkedHashMap();//記錄裏的主鍵
if (!isUpdateKey) {
for (int i = 0; i < k0.length; i++) {
if (tool.isInFields(tableKeys, k0[i].toString())) {//記錄中是否有主鍵
key_m.put(k0[i].toString(), _m.remove(k0[i].toString()));//將記錄中的主鍵移到key_m中;保證不對主鍵更新
}
}
}
Object[] fields = (_m.keySet()).toArray(); //記錄中不包含主鍵的有效字段;再次過濾掉主鍵字段的結果
Object[] keys = (key_m.keySet()).toArray(); //記錄中包含的主鍵
if (isUpdateKey) {
if (keys.length == 0 || keys.length != tableKeys.length) {
return num;
}
}
String[] kss = new String[fields.length]; //保存"鍵名=?"
for (int i = 0; i < fields.length; i++) {
kss[i] = fields[i].toString() + "=?";
}
String n_v = tool.arryToString(kss, ",");
String preparedStatementUpdate = "update " + tableName + " set " + n_v + " ";
//System.out.println(preparedStatementUpdate);
PreparedStatement pstmt = null;
try {
if (whereStr != null) {
pstmt = con.prepareStatement(preparedStatementUpdate + whereStr);//如果whereStr!=null,從這裏執行PrepareStatement更新
}
for (Map record : listRecord) {
if (whereStr == null) {
String _w = "";
if (keys.length > 0) {
Field f = db.getField(tableName, keys[0].toString());
Object _o = record.get(keys[0].toString());
String _s = "";
if (f.getTypeClassName().equals("java.lang.String")) {
_s = keys[0].toString() + " like '" + _o.toString() + "'";
} else {
_s = keys[0].toString() + " = " + _o.toString();
}
if (keys.length > 1) {
for (int i = 1; i < keys.length; i++) {
f = db.getField(tableName, keys[i].toString());
_o = record.get(keys[i].toString());
if (f.getTypeClassName().equals("java.lang.String")) {
_s = _s + " and " + keys[i].toString() + " like '" + _o.toString() + "'";
} else {
_s = _s + " and " + keys[i].toString() + " = " + _o.toString();
}
}
}
_w = " where " + _s;
}
//System.out.println(preparedStatementUpdate + _w);//批量更新
pstmt = con.prepareStatement(preparedStatementUpdate + _w);//如果whereStr==null,從這裏執行PrepareStatement更新//條件不同,只能逐條變更插入語句
}
//爲了提高運算效率,規定判斷條件優先順序:常用標準條件精確匹配、標準條件精確匹配、非標準條件精確匹配、非標準條件概略匹配、非標準條件概略小寫匹配
for (int i = 0; i < fields.length; i++) {
Field f = db.getField(tableName, fields[i].toString());
String className = f.getTypeClassName();
int index = f.getSqlType();
Object v = record.get(fields[i].toString());
if (v == null) {
pstmt.setNull(i + 1, index);//continue;
} else if (v != null) {
String _c = ((Class) v.getClass()).getName(); //增加對錶單數據的支持,在表單中獲取的數據均爲String型,固應對其進行轉換.
if ((_c.equals("java.lang.String")) && ("".equals(((String) v).trim()))) {
pstmt.setNull(i + 1, index);//continue;
} else {
if (className.equals("java.lang.String")) {
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setString(i + 1, (String) v);
}
continue;
}
if (className.equals("java.lang.Integer")) {
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setInt(i + 1, Integer.parseInt((String) v));
} else {
if (_c.equals("java.lang.Integer")) {
pstmt.setInt(i + 1, ((Integer) v).intValue());
} else {
Integer n = new Integer(v.toString());
pstmt.setInt(i + 1, n);
}
}
continue;
}
if (className.equals("java.lang.Long")) {
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setLong(i + 1, Long.parseLong((String) v));
} else {
if (_c.equals("java.lang.Long")) {
pstmt.setLong(i + 1, ((Long) v).longValue());
} else {
Long l = new Long(v.toString());
pstmt.setLong(i + 1, l);
}
}
continue;
}
if (className.equals("java.lang.Short")) {
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setShort(i + 1, Short.parseShort((String) v));
} else {
pstmt.setShort(i + 1, ((Short) v).shortValue());
}
continue;
}
if (className.equals("java.lang.Float")) {
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setFloat(i + 1, Float.parseFloat((String) v));
} else {
pstmt.setFloat(i + 1, ((Float) v).floatValue());
}
continue;
}
if (className.equals("java.lang.Double")) {
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setDouble(i + 1, Double.parseDouble((String) v));
} else {
pstmt.setDouble(i + 1, ((Double) v).doubleValue());
}
continue;
}
if (className.equals("java.lang.Boolean")) {
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setBoolean(i + 1, (Boolean.valueOf((String) v)).booleanValue());
} else {
pstmt.setBoolean(i + 1, ((Boolean) v).booleanValue());
}
continue;
}
if (className.equals("java.sql.Timestamp")) {
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
String _s = ((String) v).trim();
if (tool.matches(RegexType.chinaDate, _s)) {//如:2012-01-24
Time t = new Time(0l);
_s = _s + " " + t.toString();
pstmt.setTimestamp(i + 1, java.sql.Timestamp.valueOf(_s));
} else {
pstmt.setTimestamp(i + 1, java.sql.Timestamp.valueOf((String) v));
}
} else if (className.equals("java.sql.Date")) {
java.sql.Date _v = (java.sql.Date) v;
pstmt.setTimestamp(i + 1, new Timestamp(_v.getTime()));
} else if (className.equals("java.util.Date")) {
java.util.Date _v = (java.util.Date) v;
pstmt.setTimestamp(i + 1, new Timestamp(_v.getTime()));
} else if (className.equals("java.sql.Time")) {
java.sql.Time _v = (java.sql.Time) v;
pstmt.setTimestamp(i + 1, new Timestamp(_v.getTime()));
} else {
pstmt.setTimestamp(i + 1, new Timestamp(((java.util.Date) v).getTime()));//能支持更多的應用
//pstmt.setTimestamp(i + 1, (java.sql.Timestamp) v);//使用jsf日期轉換後獲得的結果可能不完整,這時會出現轉換異常
}
continue;
}
if (className.equals("java.sql.Date") || className.equals("java.util.Date")) {
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setDate(i + 1, java.sql.Date.valueOf((String) v));
} else if (className.equals("java.util.Date")) {
java.util.Date _v = (java.util.Date) v;
pstmt.setDate(i + 1, new java.sql.Date(_v.getTime()));
} else {
pstmt.setDate(i + 1, (java.sql.Date) v);
}
continue;
}
if (className.equals("java.sql.Time")) {
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setTime(i + 1, java.sql.Time.valueOf((String) v));
} else {
pstmt.setTime(i + 1, (java.sql.Time) v);
}
continue;
}
if (className.equals("[B") || className.equals("byte[]")) {
//SQL Server 的image、timestamp、binary類型是byte[],MySQL 的blob系列是java.lang.Object,Sybase的image是[B
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setBytes(i + 1, ((String) v).getBytes());
} else {
pstmt.setBytes(i + 1, (byte[]) v);
}
continue;
}
if (className.equals("java.sql.Blob")) {
//SQL Server 的image、timestamp、binary類型是byte[],MySQL 的blob系列是java.lang.Object,Sybase的image是[B
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setBytes(i + 1, ((String) v).getBytes());
} else {
pstmt.setBlob(i + 1, (java.sql.Blob) v);
}
continue;
}
if (className.equals("java.lang.Object")) {
//SQL Server 的image、timestamp、binary類型是byte[],MySQL 的blob系列是java.lang.Object,Sybase的image是[B
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setBytes(i + 1, ((String) v).getBytes());
} else {
pstmt.setObject(i + 1, v);
}
continue;
}
if (className.equals("java.lang.Byte")) {
//MySQL的tinyint是java.lang.Byte
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setByte(i + 1, java.lang.Byte.parseByte((String) v));
} else {
pstmt.setByte(i + 1, java.lang.Byte.parseByte(v.toString()));
}
continue;
}
if (className.equals("java.math.BigDecimal")) {
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setBigDecimal(i + 1, new BigDecimal((String) v));
} else {
pstmt.setBigDecimal(i + 1, (BigDecimal) v);
}
continue;
}
//以下部分將根據具體的數據庫需要而定,有待驗證
if (className.equals("java.sql.Clob")) {
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setString(i + 1, (String) v);//給clob類型的字段賦予字符串型
} else {
pstmt.setClob(i + 1, (java.sql.Clob) v);
}
continue;
}
//以下部分將根據具體的數據庫需要而定,有待驗證
if (className.equals("java.sql.Array")) {
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
//
} else {
pstmt.setArray(i + 1, (java.sql.Array) v);
}
continue;
}
//特殊類型,非常用,置後
if (className.equals("com.sybase.jdbc2.tds.SybTimestamp") || className.toLowerCase().indexOf("timestamp") > 0) {
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setTimestamp(i + 1, java.sql.Timestamp.valueOf((String) v));
} else {
pstmt.setTimestamp(i + 1, (java.sql.Timestamp) v);
}
continue;
}
//概略匹配
if (className.toLowerCase().indexOf("date") > 0) {
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setDate(i + 1, java.sql.Date.valueOf((String) v));
} else {
pstmt.setDate(i + 1, new java.sql.Date(((java.util.Date) v).getTime()));
}
continue;
}
if (className.toLowerCase().indexOf("time") > 0) {
if ((_c.equals("java.lang.String")) && (!"".equals(((String) v).trim()))) {
pstmt.setTime(i + 1, java.sql.Time.valueOf((String) v));
} else {
pstmt.setTime(i + 1, (java.sql.Time) v);
}
continue;
}
if (_c.equals("java.io.FileInputStream")) {
//調用如:FileInputStream in = new FileInputStream("D:\\test.jpg");的結果
pstmt.setBinaryStream(i + 1, (FileInputStream) v, ((FileInputStream) v).available());
continue;
}//java.io.FileInputStream
//其它特殊類型,非常用,置後,更多的setXXX方法詳見《年鑑》p700
}
}
}
num = num + pstmt.executeUpdate();
}
} catch (java.lang.ClassCastException ex) {
throw new SQLException("java.lang.ClassCastException: " + ex.getMessage(), ex.getCause());
} catch (NumberFormatException ex) {
throw new SQLException("NumberFormatException: " + ex.getMessage(), ex.getCause());
} catch (IOException ex) {
throw new SQLException("IOException: " + ex.getMessage(), ex.getCause());
} finally {
pstmt.close();
}
return num;
}
通配符對應的賦值方法參見“SQL數據類型與Java類的對應關係”一文