mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-14 05:23:14 +00:00
Make metadatavalue updates kinder to the database by only writing / deleting the difference between the current DB values and the in-memory values
git-svn-id: http://scm.dspace.org/svn/repo/branches/dspace-1_5_x@2660 9c30dcfa-912a-0410-8fc2-9e0234be79fd
This commit is contained in:
@@ -141,10 +141,7 @@ public class Item extends DSpaceObject
|
|||||||
clearDetails();
|
clearDetails();
|
||||||
|
|
||||||
// Get Dublin Core metadata
|
// Get Dublin Core metadata
|
||||||
TableRowIterator tri = DatabaseManager.queryTable(ourContext, "MetadataValue",
|
TableRowIterator tri = retrieveMetadata();
|
||||||
"SELECT * FROM MetadataValue WHERE item_id= ? " +
|
|
||||||
" ORDER BY metadata_field_id, place",
|
|
||||||
itemRow.getIntColumn("item_id"));
|
|
||||||
|
|
||||||
while (tri.hasNext())
|
while (tri.hasNext())
|
||||||
{
|
{
|
||||||
@@ -187,6 +184,13 @@ public class Item extends DSpaceObject
|
|||||||
context.cache(this, row.getIntColumn("item_id"));
|
context.cache(this, row.getIntColumn("item_id"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TableRowIterator retrieveMetadata() throws SQLException
|
||||||
|
{
|
||||||
|
return DatabaseManager.queryTable(ourContext, "MetadataValue",
|
||||||
|
"SELECT * FROM MetadataValue WHERE item_id= ? ORDER BY metadata_field_id, place",
|
||||||
|
itemRow.getIntColumn("item_id"));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an item from the database. The item, its Dublin Core metadata, and
|
* Get an item from the database. The item, its Dublin Core metadata, and
|
||||||
* the bundle and bitstream metadata are all loaded into memory.
|
* the bundle and bitstream metadata are all loaded into memory.
|
||||||
@@ -1463,30 +1467,41 @@ public class Item extends DSpaceObject
|
|||||||
// Redo Dublin Core if it's changed
|
// Redo Dublin Core if it's changed
|
||||||
if (dublinCoreChanged)
|
if (dublinCoreChanged)
|
||||||
{
|
{
|
||||||
// Remove existing DC
|
// Arrays to store the working information required
|
||||||
removeMetadataFromDatabase();
|
int[] placeNum = new int[dublinCore.size()];
|
||||||
|
boolean[] storedDC = new boolean[dublinCore.size()];
|
||||||
|
MetadataField[] dcFields = new MetadataField[dublinCore.size()];
|
||||||
|
|
||||||
// Add in-memory DC
|
// Work out the place numbers for the in memory DC
|
||||||
for (DCValue dcv : dublinCore)
|
for (int dcIdx = 0; dcIdx < dublinCore.size(); dcIdx++)
|
||||||
{
|
{
|
||||||
// Get the DC Type
|
DCValue dcv = dublinCore.get(dcIdx);
|
||||||
int schemaID;
|
|
||||||
MetadataSchema schema = MetadataSchema.find(ourContext,dcv.schema);
|
// Work out the place number for ordering
|
||||||
if (schema == null) {
|
int current = 0;
|
||||||
schemaID = MetadataSchema.DC_SCHEMA_ID;
|
|
||||||
} else {
|
// Key into map is "element" or "element.qualifier"
|
||||||
schemaID = schema.getSchemaID();
|
String key = dcv.element + ((dcv.qualifier == null) ? "" : ("." + dcv.qualifier));
|
||||||
|
|
||||||
|
Integer currentInteger = elementCount.get(key);
|
||||||
|
if (currentInteger != null)
|
||||||
|
{
|
||||||
|
current = currentInteger.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
MetadataField field = MetadataField.findByElement(ourContext,
|
current++;
|
||||||
schemaID, dcv.element, dcv.qualifier);
|
elementCount.put(key, Integer.valueOf(current));
|
||||||
|
|
||||||
if (field == null)
|
// Store the calculated place number, reset the stored flag, and cache the metadatafield
|
||||||
|
placeNum[dcIdx] = current;
|
||||||
|
storedDC[dcIdx] = false;
|
||||||
|
dcFields[dcIdx] = getMetadataField(dcv);
|
||||||
|
if (dcFields[dcIdx] == null)
|
||||||
{
|
{
|
||||||
// Bad DC field, log and throw exception
|
// Bad DC field, log and throw exception
|
||||||
log.warn(LogManager
|
log.warn(LogManager
|
||||||
.getHeader(ourContext, "bad_dc",
|
.getHeader(ourContext, "bad_dc",
|
||||||
"Bad DC field. SchemaID="+String.valueOf(schemaID)
|
"Bad DC field. schema="+String.valueOf(dcv.schema)
|
||||||
+ ", element: \""
|
+ ", element: \""
|
||||||
+ ((dcv.element == null) ? "null"
|
+ ((dcv.element == null) ? "null"
|
||||||
: dcv.element)
|
: dcv.element)
|
||||||
@@ -1498,37 +1513,103 @@ public class Item extends DSpaceObject
|
|||||||
: dcv.value) + "\""));
|
: dcv.value) + "\""));
|
||||||
|
|
||||||
throw new SQLException("bad_dublin_core "
|
throw new SQLException("bad_dublin_core "
|
||||||
+ "SchemaID="+String.valueOf(schemaID)+", "
|
+ "schema="+dcv.schema+", "
|
||||||
+ dcv.element
|
+ dcv.element
|
||||||
+ " " + dcv.qualifier);
|
+ " " + dcv.qualifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Work out the place number for ordering
|
|
||||||
int current = 0;
|
|
||||||
|
|
||||||
// Key into map is "element" or "element.qualifier"
|
|
||||||
String key = dcv.element
|
|
||||||
+ ((dcv.qualifier == null) ? "" : ("." + dcv.qualifier));
|
|
||||||
|
|
||||||
Integer currentInteger = (Integer) elementCount.get(key);
|
|
||||||
|
|
||||||
if (currentInteger != null)
|
|
||||||
{
|
|
||||||
current = currentInteger.intValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
current++;
|
// Now the precalculations are done, iterate through the existing metadata
|
||||||
elementCount.put(key, new Integer(current));
|
// looking for matches
|
||||||
|
TableRowIterator tri = retrieveMetadata();
|
||||||
|
if (tri != null)
|
||||||
|
{
|
||||||
|
while (tri.hasNext())
|
||||||
|
{
|
||||||
|
TableRow tr = tri.next();
|
||||||
|
// Assume that we will remove this row, unless we get a match
|
||||||
|
boolean removeRow = true;
|
||||||
|
|
||||||
|
// Go through the in-memory metadata, unless we've already decided to keep this row
|
||||||
|
for (int dcIdx = 0; dcIdx < dublinCore.size() && removeRow; dcIdx++)
|
||||||
|
{
|
||||||
|
// Only process if this metadata has not already been matched to something in the DB
|
||||||
|
if (!storedDC[dcIdx])
|
||||||
|
{
|
||||||
|
boolean matched = true;
|
||||||
|
DCValue dcv = dublinCore.get(dcIdx);
|
||||||
|
|
||||||
|
// Check the metadata field is the same
|
||||||
|
if (matched && dcFields[dcIdx].getFieldID() != tr.getIntColumn("metadata_field_id"))
|
||||||
|
matched = false;
|
||||||
|
|
||||||
|
// Check the place is the same
|
||||||
|
if (matched && placeNum[dcIdx] != tr.getIntColumn("place"))
|
||||||
|
matched = false;
|
||||||
|
|
||||||
|
// Check the text is the same
|
||||||
|
if (matched)
|
||||||
|
{
|
||||||
|
String text = tr.getStringColumn("text_value");
|
||||||
|
if (dcv.value == null && text == null)
|
||||||
|
matched = true;
|
||||||
|
else if (dcv.value != null && dcv.value.equals(text))
|
||||||
|
matched = true;
|
||||||
|
else
|
||||||
|
matched = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the language is the same
|
||||||
|
if (matched)
|
||||||
|
{
|
||||||
|
String lang = tr.getStringColumn("text_lang");
|
||||||
|
if (dcv.language == null && lang == null)
|
||||||
|
matched = true;
|
||||||
|
else if (dcv.language != null && dcv.language.equals(lang))
|
||||||
|
matched = true;
|
||||||
|
else
|
||||||
|
matched = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the db record is identical to the in memory values
|
||||||
|
if (matched)
|
||||||
|
{
|
||||||
|
// Flag that the metadata is already in the DB
|
||||||
|
storedDC[dcIdx] = true;
|
||||||
|
|
||||||
|
// Flag that we are not going to remove the row
|
||||||
|
removeRow = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If after processing all the metadata values, we didn't find a match
|
||||||
|
// delete this row from the DB
|
||||||
|
if (removeRow)
|
||||||
|
{
|
||||||
|
DatabaseManager.delete(ourContext, tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add missing in-memory DC
|
||||||
|
for (int dcIdx = 0; dcIdx < dublinCore.size(); dcIdx++)
|
||||||
|
{
|
||||||
|
// Only write values that are not already in the db
|
||||||
|
if (!storedDC[dcIdx])
|
||||||
|
{
|
||||||
|
DCValue dcv = dublinCore.get(dcIdx);
|
||||||
|
|
||||||
// Write DCValue
|
// Write DCValue
|
||||||
MetadataValue metadata = new MetadataValue();
|
MetadataValue metadata = new MetadataValue();
|
||||||
metadata.setItemId(getID());
|
metadata.setItemId(getID());
|
||||||
metadata.setFieldId(field.getFieldID());
|
metadata.setFieldId(dcFields[dcIdx].getFieldID());
|
||||||
metadata.setValue(dcv.value);
|
metadata.setValue(dcv.value);
|
||||||
metadata.setLanguage(dcv.language);
|
metadata.setLanguage(dcv.language);
|
||||||
metadata.setPlace(current);
|
metadata.setPlace(placeNum[dcIdx]);
|
||||||
metadata.create(ourContext);
|
metadata.create(ourContext);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ourContext.addEvent(new Event(Event.MODIFY_METADATA, Constants.ITEM, getID(), getDetails()));
|
ourContext.addEvent(new Event(Event.MODIFY_METADATA, Constants.ITEM, getID(), getDetails()));
|
||||||
dublinCoreChanged = false;
|
dublinCoreChanged = false;
|
||||||
@@ -1542,6 +1623,27 @@ public class Item extends DSpaceObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MetadataField getMetadataField(DCValue dcv) throws SQLException, AuthorizeException
|
||||||
|
{
|
||||||
|
return MetadataField.findByElement(ourContext,
|
||||||
|
getMetadataSchemaID(dcv), dcv.element, dcv.qualifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getMetadataSchemaID(DCValue dcv) throws SQLException
|
||||||
|
{
|
||||||
|
int schemaID;
|
||||||
|
MetadataSchema schema = MetadataSchema.find(ourContext,dcv.schema);
|
||||||
|
if (schema == null)
|
||||||
|
{
|
||||||
|
schemaID = MetadataSchema.DC_SCHEMA_ID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
schemaID = schema.getSchemaID();
|
||||||
|
}
|
||||||
|
return schemaID;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Withdraw the item from the archive. It is kept in place, and the content
|
* Withdraw the item from the archive. It is kept in place, and the content
|
||||||
* and metadata are not deleted, but it is not publicly accessible.
|
* and metadata are not deleted, but it is not publicly accessible.
|
||||||
|
Reference in New Issue
Block a user