diff --git a/dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseManager.java b/dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseManager.java index 869502a2fe..74acabf99d 100644 --- a/dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseManager.java +++ b/dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseManager.java @@ -632,22 +632,32 @@ public class DatabaseManager StringBuffer sql = new StringBuffer().append("update ").append(table) .append(" set "); + List columns = new ArrayList(); ColumnInfo pk = getPrimaryKeyColumnInfo(table); ColumnInfo[] info = getNonPrimaryKeyColumns(table); + String seperator = ""; for (int i = 0; i < info.length; i++) { - sql.append((i == 0) ? "" : ", ").append(info[i].getName()).append( - " = ?"); + // Only update this column if it has changed + if (row.hasColumnChanged(info[i].getName())) + { + sql.append(seperator).append(info[i].getName()).append(" = ?"); + columns.add(info[i]); + seperator = ", "; + } } - sql.append(" where ").append(pk.getName()).append(" = ?"); + // Only execute the update if there is anything to update + if (columns.size() > 0) + { + sql.append(" where ").append(pk.getName()).append(" = ?"); + columns.add(pk); - List columns = new ArrayList(); - columns.addAll(Arrays.asList(info)); - columns.add(pk); + return execute(context.getDBConnection(), sql.toString(), columns, row); + } - return execute(context.getDBConnection(), sql.toString(), columns, row); + return 1; } /** @@ -1107,6 +1117,8 @@ public class DatabaseManager } } + // Now that we've prepped the TableRow, reset the flags so that we can detect which columns have changed + row.resetChanged(); return row; } diff --git a/dspace-api/src/main/java/org/dspace/storage/rdbms/TableRow.java b/dspace-api/src/main/java/org/dspace/storage/rdbms/TableRow.java index fcc8f8eb5e..7bc9d239ce 100644 --- a/dspace-api/src/main/java/org/dspace/storage/rdbms/TableRow.java +++ b/dspace-api/src/main/java/org/dspace/storage/rdbms/TableRow.java @@ -67,6 +67,8 @@ public class TableRow */ private Map data = new HashMap(); + private Map changed = new HashMap(); + /** * Constructor * @@ -82,6 +84,7 @@ public class TableRow { this.table = table; nullColumns(columns); + resetChanged(columns); } /** @@ -107,6 +110,18 @@ public class TableRow return data.get(canonicalize(column)) != null; } + /** + * Return true if this row contains this column and the value has been updated. + * + * @param column + * The column name (case-insensitive) + * @return True if this row contains a column with this name. + */ + public boolean hasColumnChanged(String column) + { + return changed.get(canonicalize(column)) == Boolean.TRUE; + } + /** * Return true if the column is an SQL NULL. * @@ -387,15 +402,26 @@ public class TableRow throw new IllegalArgumentException("No such column " + column); } + String canonName = canonicalize(column); if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) { // if oracle, use 1 or 0 for true/false - data.put(canonicalize(column), b ? new Integer(1) : new Integer(0)); + Integer value = b ? new Integer(1) : new Integer(0); + if (!value.equals(data.get(canonName))) + { + data.put(canonName, value); + changed.put(canonName, Boolean.TRUE); + } } else { // default to postgres true/false - data.put(canonicalize(column), b ? Boolean.TRUE : Boolean.FALSE); + Boolean value = b ? Boolean.TRUE : Boolean.FALSE; + if (!value.equals(data.get(canonName))) + { + data.put(canonName, value); + changed.put(canonName, Boolean.TRUE); + } } } @@ -416,7 +442,13 @@ public class TableRow throw new IllegalArgumentException("No such column " + column); } - data.put(canonicalize(column), (s == null) ? NULL_OBJECT : s); + String canonName = canonicalize(column); + Object value = (s == null) ? NULL_OBJECT : s; + if (!value.equals(data.get(canonName))) + { + data.put(canonName, value); + changed.put(canonName, Boolean.TRUE); + } } /** @@ -436,7 +468,13 @@ public class TableRow throw new IllegalArgumentException("No such column " + column); } - data.put(canonicalize(column), new Integer(i)); + String canonName = canonicalize(column); + Integer value = new Integer(i); + if (!value.equals(data.get(canonName))) + { + data.put(canonName, value); + changed.put(canonName, Boolean.TRUE); + } } /** @@ -456,7 +494,13 @@ public class TableRow throw new IllegalArgumentException("No such column " + column); } - data.put(canonicalize(column), new Long(l)); + String canonName = canonicalize(column); + Long value = new Long(l); + if (!value.equals(data.get(canonName))) + { + data.put(canonName, value); + changed.put(canonName, Boolean.TRUE); + } } /** @@ -477,14 +521,13 @@ public class TableRow throw new IllegalArgumentException("No such column " + column); } - if (d == null) + String canonName = canonicalize(column); + Object value = (d == null) ? NULL_OBJECT : d; + if (!value.equals(data.get(canonName))) { - setColumnNull(canonicalize(column)); - - return; + data.put(canonName, value); + changed.put(canonName, Boolean.TRUE); } - - data.put(canonicalize(column), d); } //////////////////////////////////////// @@ -583,6 +626,29 @@ public class TableRow } } + private void resetChanged(List columns) + { + for (Iterator iterator = columns.iterator(); iterator.hasNext();) + { + changed.put(canonicalize((String) iterator.next()), Boolean.FALSE); + } + } + + /** + * package private method to reset the flags of which columns have been updated + * This is used by the database manager after it has finished processing the contents + * of a resultset, so that it can update only columns that have been updated. + * Note that this method does not reset the values themselves, only the flags, + * and should not be considered safe to call from anywhere other than the DatabaseManager. + */ + void resetChanged() + { + for (Iterator iterator = changed.keySet().iterator(); iterator.hasNext();) + { + changed.put(canonicalize((String) iterator.next()), Boolean.FALSE); + } + } + /** * Internal method to set column to null. The public method ensures that * column actually exists. @@ -591,6 +657,11 @@ public class TableRow */ private void setColumnNullInternal(String column) { - data.put(canonicalize(column), NULL_OBJECT); + String canonName = canonicalize(column); + if (data.get(canonName) != NULL_OBJECT) + { + data.put(canonName, NULL_OBJECT); + changed.put(canonName, Boolean.TRUE); + } } }