Added multi-select for property values

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@16542 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2009-09-27 20:57:47 +00:00
parent fb895d06a8
commit ac71c4f7d7
7 changed files with 252 additions and 0 deletions

View File

@@ -21,6 +21,8 @@
<typeAlias alias="PropertyLink" type="org.alfresco.repo.domain.propval.PropertyLinkEntity"/> <typeAlias alias="PropertyLink" type="org.alfresco.repo.domain.propval.PropertyLinkEntity"/>
<typeAlias alias="PropertyUniqueContext" type="org.alfresco.repo.domain.propval.PropertyUniqueContextEntity"/> <typeAlias alias="PropertyUniqueContext" type="org.alfresco.repo.domain.propval.PropertyUniqueContextEntity"/>
<typeAlias alias="PropertyIdSearchRow" type="org.alfresco.repo.domain.propval.PropertyIdSearchRow"/> <typeAlias alias="PropertyIdSearchRow" type="org.alfresco.repo.domain.propval.PropertyIdSearchRow"/>
<typeAlias alias="PropertyIdQueryResult" type="org.alfresco.repo.domain.propval.PropertyIdQueryResult"/>
<typeAlias alias="PropertyIdQueryParameter" type="org.alfresco.repo.domain.propval.PropertyIdQueryParameter"/>
<!-- --> <!-- -->
<!-- Result Maps --> <!-- Result Maps -->
@@ -100,6 +102,10 @@
<result property="stringValue" column="prop_string_value" jdbcType="VARCHAR" javaType="java.lang.String"/> <result property="stringValue" column="prop_string_value" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result property="serializableValue" column="prop_serializable_value" jdbcType="BLOB" javaType="java.io.Serializable"/> <result property="serializableValue" column="prop_serializable_value" jdbcType="BLOB" javaType="java.io.Serializable"/>
</resultMap> </resultMap>
<resultMap id="result_PropertyIdQueryResult" class="PropertyIdQueryResult">
<result property="propId" column="prop_id" jdbcType="BIGINT" javaType="long"/>
<result property="propValues" resultMap="alfresco.propval.result_PropertyIdSearchRow"/>
</resultMap>
<!-- --> <!-- -->
<!-- Parameter Maps --> <!-- Parameter Maps -->
@@ -364,6 +370,36 @@
pl.root_prop_id = #id# pl.root_prop_id = #id#
</select> </select>
<!-- Get the property values by a list of IDs -->
<select id="select_PropertiesByIds" parameterClass="PropertyIdQueryParameter" resultMap="result_PropertyIdQueryResult">
select
pl.root_prop_id as prop_id,
pl.root_prop_id as link_root_prop_id,
pl.prop_index as link_prop_index,
pl.contained_in as link_contained_in,
pl.key_prop_id as link_key_prop_id,
pl.value_prop_id as link_value_prop_id,
pv.actual_type_id as prop_actual_type_id,
pv.persisted_type as prop_persisted_type,
pv.long_value as prop_long_value,
dv.double_value as prop_double_value,
sv.string_value as prop_string_value,
serv.serializable_value as prop_serializable_value
from
alf_prop_link pl
join alf_prop_value pv on (pl.value_prop_id = pv.id)
left join alf_prop_double_value dv on (dv.id = pv.long_value and pv.persisted_type = 2)
left join alf_prop_string_value sv on (sv.id = pv.long_value and (pv.persisted_type = 3 || pv.persisted_type = 5))
left join alf_prop_serializable_value serv on (serv.id = pv.long_value and pv.persisted_type = 4)
<dynamic prepend="where pl.root_prop_id in ">
<iterate property="rootPropIds" open="(" close=")" conjunction=", ">
#rootPropIds[]#
</iterate>
</dynamic>
order by
root_prop_id
</select>
<select id="select_PropertyRootById" parameterClass="PropertyRoot" resultMap="result_PropertyRoot"> <select id="select_PropertyRootById" parameterClass="PropertyRoot" resultMap="result_PropertyRoot">
select select
id, id,

View File

@@ -796,6 +796,11 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO
return entityPair.getSecond(); return entityPair.getSecond();
} }
public void getPropertiesByIds(List<Long> ids, PropertyFinderCallback callback)
{
findPropertiesByIds(ids, callback);
}
/** /**
* {@inheritDoc} * {@inheritDoc}
* @see #createPropertyImpl(Serializable, int, int) * @see #createPropertyImpl(Serializable, int, int)
@@ -1032,6 +1037,7 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO
} }
protected abstract List<PropertyIdSearchRow> findPropertyById(Long id); protected abstract List<PropertyIdSearchRow> findPropertyById(Long id);
protected abstract void findPropertiesByIds(List<Long> ids, PropertyFinderCallback callback);
protected abstract Long createPropertyRoot(); protected abstract Long createPropertyRoot();
protected abstract PropertyRootEntity getPropertyRoot(Long id); protected abstract PropertyRootEntity getPropertyRoot(Long id);
protected abstract PropertyRootEntity updatePropertyRoot(PropertyRootEntity entity); protected abstract PropertyRootEntity updatePropertyRoot(PropertyRootEntity entity);

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.domain.propval;
import java.util.List;
/**
* Query parameters for searching <b>alf_prop_link</b> by IDs.
*
* @author Derek Hulley
* @since 3.2
*/
public class PropertyIdQueryParameter
{
private List<Long> rootPropIds;
public PropertyIdQueryParameter()
{
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder(512);
sb.append("PropertyIdQueryParameter")
.append(", rootPropIds=").append(rootPropIds)
.append("]");
return sb.toString();
}
public List<Long> getRootPropIds()
{
return rootPropIds;
}
public void setRootPropIds(List<Long> rootPropIds)
{
this.rootPropIds = rootPropIds;
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.domain.propval;
import java.util.List;
/**
* Entity bean for rolled up <b>alf_prop_link</b> results.
*
* @author Derek Hulley
* @since 3.2
*/
public class PropertyIdQueryResult
{
private Long propId;
private List<PropertyIdSearchRow> propValues;
public PropertyIdQueryResult()
{
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder(512);
sb.append("PropertyLinkQueryResult")
.append("[ propId=").append(propId)
.append(", propValues=").append(propValues.size())
.append("]");
return sb.toString();
}
public Long getPropId()
{
return propId;
}
public void setPropId(Long propId)
{
this.propId = propId;
}
public List<PropertyIdSearchRow> getPropValues()
{
return propValues;
}
public void setPropValues(List<PropertyIdSearchRow> propValues)
{
this.propValues = propValues;
}
}

View File

@@ -215,6 +215,15 @@ public interface PropertyValueDAO
//================================ //================================
// 'alf_prop_root' accessors // 'alf_prop_root' accessors
//================================ //================================
/**
* A callback for handling return properties
*/
public interface PropertyFinderCallback
{
public void handleProperty(Long id, Serializable value);
}
/** /**
* Use for accessing non-unique, exploded properties; see interface comments. * Use for accessing non-unique, exploded properties; see interface comments.
* <p/> * <p/>
@@ -225,6 +234,16 @@ public interface PropertyValueDAO
* @throws DataIntegrityViolationException if the ID is invalid * @throws DataIntegrityViolationException if the ID is invalid
*/ */
Serializable getPropertyById(Long id); Serializable getPropertyById(Long id);
/**
* Use for accessing non-unique, exploded properties; see interface comments.
* <p/>
* <b>alf_prop_root</b> accessor: get all properties based on the database IDs
*
* @param ids the IDs (may not be <tt>null</tt>; may be empty)
* @param callback the callback to handle the results
* @throws DataIntegrityViolationException if any of the the IDs are invalid
*/
void getPropertiesByIds(List<Long> ids, PropertyFinderCallback callback);
/** /**
* Use for accessing non-unique, exploded properties; see interface comments. * Use for accessing non-unique, exploded properties; see interface comments.
* <p/> * <p/>

View File

@@ -26,9 +26,11 @@ package org.alfresco.repo.domain.propval;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
@@ -36,6 +38,7 @@ import javax.naming.CompositeName;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.alfresco.repo.domain.propval.PropertyValueDAO.PropertyFinderCallback;
import org.alfresco.repo.props.PropertyUniqueConstraintViolation; import org.alfresco.repo.props.PropertyUniqueConstraintViolation;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
@@ -498,6 +501,22 @@ public class PropertyValueDAOTest extends TestCase
assertNotNull(entityValueCheck); assertNotNull(entityValueCheck);
assertEquals(value, entityValueCheck); assertEquals(value, entityValueCheck);
// Test the callback for multiple IDs
final Map<Long, Serializable> propsById = new HashMap<Long, Serializable>();
PropertyFinderCallback finderCallback = new PropertyFinderCallback()
{
public void handleProperty(Long id, Serializable value)
{
propsById.put(id, value);
}
};
List<Long> entityIds = Collections.singletonList(entityId);
propertyValueDAO.getPropertiesByIds(entityIds, finderCallback);
assertEquals("Should be exactly one value in map", 1, propsById.size());
assertTrue("Expected ID to be in map", propsById.containsKey(entityId));
assertEquals("Value was not retrieved correctly", value, propsById.get(entityId));
// Done // Done
return entityId; return entityId;
} }

View File

@@ -28,10 +28,13 @@ import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import org.alfresco.ibatis.RollupRowHandler;
import org.alfresco.repo.domain.propval.AbstractPropertyValueDAOImpl; import org.alfresco.repo.domain.propval.AbstractPropertyValueDAOImpl;
import org.alfresco.repo.domain.propval.PropertyClassEntity; import org.alfresco.repo.domain.propval.PropertyClassEntity;
import org.alfresco.repo.domain.propval.PropertyDateValueEntity; import org.alfresco.repo.domain.propval.PropertyDateValueEntity;
import org.alfresco.repo.domain.propval.PropertyDoubleValueEntity; import org.alfresco.repo.domain.propval.PropertyDoubleValueEntity;
import org.alfresco.repo.domain.propval.PropertyIdQueryParameter;
import org.alfresco.repo.domain.propval.PropertyIdQueryResult;
import org.alfresco.repo.domain.propval.PropertyIdSearchRow; import org.alfresco.repo.domain.propval.PropertyIdSearchRow;
import org.alfresco.repo.domain.propval.PropertyLinkEntity; import org.alfresco.repo.domain.propval.PropertyLinkEntity;
import org.alfresco.repo.domain.propval.PropertyRootEntity; import org.alfresco.repo.domain.propval.PropertyRootEntity;
@@ -44,6 +47,8 @@ import org.alfresco.repo.domain.propval.PropertyValueEntity.PersistedType;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
import org.springframework.orm.ibatis.SqlMapClientTemplate; import org.springframework.orm.ibatis.SqlMapClientTemplate;
import com.ibatis.sqlmap.client.event.RowHandler;
/** /**
* iBatis-specific implementation of the PropertyValue DAO. * iBatis-specific implementation of the PropertyValue DAO.
* *
@@ -78,6 +83,7 @@ public class PropertyValueDAOImpl extends AbstractPropertyValueDAOImpl
private static final String INSERT_PROPERTY_VALUE = "alfresco.propval.insert_PropertyValue"; private static final String INSERT_PROPERTY_VALUE = "alfresco.propval.insert_PropertyValue";
private static final String SELECT_PROPERTY_BY_ID = "alfresco.propval.select_PropertyById"; private static final String SELECT_PROPERTY_BY_ID = "alfresco.propval.select_PropertyById";
private static final String SELECT_PROPERTIES_BY_IDS = "alfresco.propval.select_PropertiesByIds";
private static final String SELECT_PROPERTY_ROOT_BY_ID = "alfresco.propval.select_PropertyRootById"; private static final String SELECT_PROPERTY_ROOT_BY_ID = "alfresco.propval.select_PropertyRootById";
private static final String INSERT_PROPERTY_ROOT = "alfresco.propval.insert_PropertyRoot"; private static final String INSERT_PROPERTY_ROOT = "alfresco.propval.insert_PropertyRoot";
private static final String UPDATE_PROPERTY_ROOT = "alfresco.propval.update_PropertyRoot"; private static final String UPDATE_PROPERTY_ROOT = "alfresco.propval.update_PropertyRoot";
@@ -455,6 +461,36 @@ public class PropertyValueDAOImpl extends AbstractPropertyValueDAOImpl
return results; return results;
} }
private static final String[] KEY_COLUMNS_FINDBYIDS = new String[] {"propId"};
@Override
protected void findPropertiesByIds(List<Long> ids, final PropertyFinderCallback callback)
{
RowHandler valueRowHandler = new RowHandler()
{
public void handleRow(Object valueObject)
{
PropertyIdQueryResult result = (PropertyIdQueryResult) valueObject;
Long id = result.getPropId();
// Make the serializable value
List<PropertyIdSearchRow> rows = result.getPropValues();
Serializable value = convertPropertyIdSearchRows(rows);
callback.handleProperty(id, value);
}
};
// A row handler to roll up individual rows
RollupRowHandler rollupRowHandler = new RollupRowHandler(
KEY_COLUMNS_FINDBYIDS,
"propValues",
valueRowHandler);
// Query using the IDs
PropertyIdQueryParameter params = new PropertyIdQueryParameter();
params.setRootPropIds(ids);
template.queryWithRowHandler(SELECT_PROPERTIES_BY_IDS, params, rollupRowHandler);
// Process any remaining results
rollupRowHandler.processLastResults();
// Done
}
@Override @Override
protected Long createPropertyRoot() protected Long createPropertyRoot()
{ {