Full resultset audit queries

- Use RollupRowHandler and nested ResultMap
 - Audit Map values are pulled back with entries


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@16130 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2009-09-07 15:48:00 +00:00
parent a6eb590cc9
commit fadc101ce4
6 changed files with 87 additions and 49 deletions

View File

@@ -46,8 +46,7 @@
</resultMap> </resultMap>
<resultMap id="result_AuditQueryAllValues" <resultMap id="result_AuditQueryAllValues"
extends="alfresco.audit.result_AuditQueryNoValues" extends="alfresco.audit.result_AuditQueryNoValues"
class="AuditQueryResult" class="AuditQueryResult">
groupBy="auditEntryId">
<result property="auditValues" resultMap="alfresco.propval.result_PropertyIdSearchRow"/> <result property="auditValues" resultMap="alfresco.propval.result_PropertyIdSearchRow"/>
</resultMap> </resultMap>

View File

@@ -38,6 +38,7 @@ import org.alfresco.repo.audit.AuditState;
import org.alfresco.repo.audit.hibernate.HibernateAuditDAO; import org.alfresco.repo.audit.hibernate.HibernateAuditDAO;
import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.domain.contentdata.ContentDataDAO; import org.alfresco.repo.domain.contentdata.ContentDataDAO;
import org.alfresco.repo.domain.propval.PropertyIdSearchRow;
import org.alfresco.repo.domain.propval.PropertyValueDAO; import org.alfresco.repo.domain.propval.PropertyValueDAO;
import org.alfresco.service.cmr.audit.AuditInfo; import org.alfresco.service.cmr.audit.AuditInfo;
import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback; import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback;
@@ -298,15 +299,39 @@ public abstract class AbstractAuditDAOImpl implements AuditDAO
return; return;
} }
// Get the value map // Get the value map
// TODO: Should be done with a nested resultmapping Map<String, Serializable> auditValues;
Long auditValuesId = row.getAuditValuesId(); List<PropertyIdSearchRow> propMapRows = row.getAuditValues();
Pair<Long, Serializable> auditValuesPair = propertyValueDAO.getPropertyValueById(auditValuesId); if (propMapRows == null)
if (auditValuesPair == null)
{ {
// Ignore // Use the audit values ID
return; Long auditValuesId = row.getAuditValuesId();
Pair<Long, Serializable> auditValuesPair = propertyValueDAO.getPropertyValueById(auditValuesId);
if (auditValuesPair == null)
{
// Ignore
logger.warn("Audit entry not joined to audit properties: " + row);
return;
}
auditValues = (Map<String, Serializable>) auditValuesPair.getSecond();
}
else
{
// Resolve the map
try
{
auditValues = (Map<String, Serializable>) propertyValueDAO.convertPropertyIdSearchRows(propMapRows);
}
catch (ClassCastException e)
{
logger.warn("Audit entry not linked to a Map<String, Serializable> value: " + row);
return;
}
if (auditValues == null)
{
logger.warn("Audit entry incompletely joined to audit properties: " + row);
return;
}
} }
Map<String, Serializable> auditValues = (Map<String, Serializable>) auditValuesPair.getSecond();
more = callback.handleAuditEntry( more = callback.handleAuditEntry(
row.getAuditEntryId(), row.getAuditEntryId(),
row.getAuditAppName(), row.getAuditAppName(),

View File

@@ -29,6 +29,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.alfresco.ibatis.RollupRowHandler;
import org.alfresco.repo.domain.audit.AbstractAuditDAOImpl; import org.alfresco.repo.domain.audit.AbstractAuditDAOImpl;
import org.alfresco.repo.domain.audit.AuditApplicationEntity; import org.alfresco.repo.domain.audit.AuditApplicationEntity;
import org.alfresco.repo.domain.audit.AuditEntryEntity; import org.alfresco.repo.domain.audit.AuditEntryEntity;
@@ -175,25 +176,38 @@ public class AuditDAOImpl extends AbstractAuditDAOImpl
params.setAuditFromTime(from); params.setAuditFromTime(from);
params.setAuditToTime(to); params.setAuditToTime(to);
// RowHandlers in RowHandlers: See 'groupBy' issue https://issues.apache.org/jira/browse/IBATIS-503
RowHandler shreddedRowHandler = new RowHandler()
{
public void handleRow(Object valueObject)
{
rowHandler.processResult((AuditQueryResult)valueObject);
}
};
RollupRowHandler rollupRowHandler = new RollupRowHandler(
new String[] {"auditEntryId"},
"auditValues",
shreddedRowHandler,
maxResults);
if (maxResults > 0) if (maxResults > 0)
{ {
List<AuditQueryResult> rows = template.queryForList(SELECT_ENTRIES_SIMPLE, params, 0, maxResults); // Calculate the maximum results required
int sqlMaxResults = (maxResults > 0 ? ((maxResults+1) * 20) : Integer.MAX_VALUE);
List<AuditQueryResult> rows = template.queryForList(SELECT_ENTRIES_WITH_VALUES, params, 0, sqlMaxResults);
for (AuditQueryResult row : rows) for (AuditQueryResult row : rows)
{ {
rowHandler.processResult(row); rollupRowHandler.handleRow(row);
} }
// Don't process last result:
// rollupRowHandler.processLastResults();
// The last result may be incomplete
} }
else else
{ {
RowHandler rowHandlerInternal = new RowHandler() template.queryWithRowHandler(SELECT_ENTRIES_WITH_VALUES, params, rollupRowHandler);
{ rollupRowHandler.processLastResults();
public void handleRow(Object valueObject)
{
AuditQueryResult row = (AuditQueryResult) valueObject;
rowHandler.processResult(row);
}
};
template.queryWithRowHandler(SELECT_ENTRIES_SIMPLE, params, rowHandlerInternal);
} }
} }
} }

View File

@@ -833,7 +833,7 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO
protected abstract PropertyValueEntity createPropertyValue(Serializable value); protected abstract PropertyValueEntity createPropertyValue(Serializable value);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected Serializable convertPropertyIdSearchRows(List<PropertyIdSearchRow> rows) public Serializable convertPropertyIdSearchRows(List<PropertyIdSearchRow> rows)
{ {
/* /*
* The results are ordered by the root_prop_id, current_prop_id and value_prop_id. * The results are ordered by the root_prop_id, current_prop_id and value_prop_id.
@@ -843,8 +843,21 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO
final Map<Long, Serializable> values = new HashMap<Long, Serializable>(rows.size()); final Map<Long, Serializable> values = new HashMap<Long, Serializable>(rows.size());
List<PropertyLinkEntity> keyRows = new ArrayList<PropertyLinkEntity>(5); List<PropertyLinkEntity> keyRows = new ArrayList<PropertyLinkEntity>(5);
Serializable result = null; Serializable result = null;
Long rootPropId = null;
for (PropertyIdSearchRow row : rows) for (PropertyIdSearchRow row : rows)
{ {
// Check that we are handling a single root property
if (rootPropId == null)
{
rootPropId = row.getLinkEntity().getRootPropId();
}
else if (!rootPropId.equals(row.getLinkEntity().getRootPropId()))
{
throw new IllegalArgumentException(
"The root_prop_id for the property search rows must not change: \n" +
" Rows: " + rows);
}
PropertyLinkEntity linkEntity = row.getLinkEntity(); PropertyLinkEntity linkEntity = row.getLinkEntity();
PropertyValueEntity valueEntity = row.getValueEntity(); PropertyValueEntity valueEntity = row.getValueEntity();
// Construct the value (Maps and Collections should be CONSTRUCTABLE) // Construct the value (Maps and Collections should be CONSTRUCTABLE)

View File

@@ -43,34 +43,6 @@ public class PropertyIdSearchRow
valueEntity = new PropertyValueEntity(); valueEntity = new PropertyValueEntity();
} }
// @Override
// public int hashCode()
// {
// return (int) rootCollectionPropId + (int) valuePropId;
// }
//
// @Override
// public boolean equals(Object obj)
// {
// if (this == obj)
// {
// return true;
// }
// else if (obj instanceof PropertyCollectionLinkEntity)
// {
// PropertyCollectionLinkEntity that = (PropertyCollectionLinkEntity) obj;
// return
// this.rootCollectionPropId == that.rootCollectionPropId &&
// this.currentCollectionPropId == that.currentCollectionPropId &&
// this.valuePropId == that.valuePropId &&
// this.keyPropId == that.keyPropId;
// }
// else
// {
// return false;
// }
// }
//
@Override @Override
public String toString() public String toString()
{ {

View File

@@ -26,6 +26,7 @@ package org.alfresco.repo.domain.propval;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.List;
import org.alfresco.repo.domain.CrcHelper; import org.alfresco.repo.domain.CrcHelper;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
@@ -195,4 +196,18 @@ public interface PropertyValueDAO
* @param maxDepth the maximum depth of collections and maps to iterate into * @param maxDepth the maximum depth of collections and maps to iterate into
*/ */
Pair<Long, Serializable> getOrCreatePropertyValue(Serializable value, int maxDepth); Pair<Long, Serializable> getOrCreatePropertyValue(Serializable value, int maxDepth);
/**
* Utility method to convert property query results into the original value. Note
* that the rows must all share the same root property ID.
* <p/>
* If the rows passed in don't constitute a valid, full property - they don't contain all
* the link entities for the property - then the result may be <tt>null</tt>.
*
* @param rows the search results for a single root property
* @return Returns the root property as originally persisted, or <tt>null</tt>
* if the rows don't represent a complete property
* @throws IllegalArgumentException if rows don't all share the same root property ID
*/
Serializable convertPropertyIdSearchRows(List<PropertyIdSearchRow> rows);
} }