mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Added table and DAO: alf_prop_unique_ctx
- Ensure uniqueness across any three (incl. null) Serializable values - Required to support RM rma:identifier contextual uniqueness DB Update for MySQL: drop table if exists alf_prop_unique_ctx; CREATE TABLE alf_prop_unique_ctx ( id BIGINT NOT NULL AUTO_INCREMENT, version SMALLINT NOT NULL, value1_prop_id BIGINT NOT NULL, value2_prop_id BIGINT NOT NULL, value3_prop_id BIGINT NOT NULL, UNIQUE INDEX idx_alf_prop_unique_ctx (value1_prop_id, value2_prop_id, value3_prop_id), CONSTRAINT fk_alf_prop_unique_ctx_1 FOREIGN KEY (value1_prop_id) REFERENCES alf_prop_value (id) ON DELETE CASCADE, CONSTRAINT fk_alf_prop_unique_ctx_2 FOREIGN KEY (value2_prop_id) REFERENCES alf_prop_value (id) ON DELETE CASCADE, CONSTRAINT fk_alf_prop_unique_ctx_3 FOREIGN KEY (value3_prop_id) REFERENCES alf_prop_value (id) ON DELETE CASCADE, PRIMARY KEY (id) ); git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@16417 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -93,6 +93,20 @@ CREATE TABLE alf_prop_link
|
|||||||
PRIMARY KEY (root_prop_id, contained_in, prop_index)
|
PRIMARY KEY (root_prop_id, contained_in, prop_index)
|
||||||
) ENGINE=InnoDB;
|
) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
CREATE TABLE alf_prop_unique_ctx
|
||||||
|
(
|
||||||
|
id BIGINT NOT NULL AUTO_INCREMENT,
|
||||||
|
version SMALLINT NOT NULL,
|
||||||
|
value1_prop_id BIGINT NOT NULL,
|
||||||
|
value2_prop_id BIGINT NOT NULL,
|
||||||
|
value3_prop_id BIGINT NOT NULL,
|
||||||
|
UNIQUE INDEX idx_alf_prop_unique_ctx (value1_prop_id, value2_prop_id, value3_prop_id),
|
||||||
|
CONSTRAINT fk_alf_prop_unique_ctx_1 FOREIGN KEY (value1_prop_id) REFERENCES alf_prop_value (id) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fk_alf_prop_unique_ctx_2 FOREIGN KEY (value2_prop_id) REFERENCES alf_prop_value (id) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fk_alf_prop_unique_ctx_3 FOREIGN KEY (value3_prop_id) REFERENCES alf_prop_value (id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
)
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Record script finish
|
-- Record script finish
|
||||||
--
|
--
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
<typeAlias alias="PropertyValue" type="org.alfresco.repo.domain.propval.PropertyValueEntity"/>
|
<typeAlias alias="PropertyValue" type="org.alfresco.repo.domain.propval.PropertyValueEntity"/>
|
||||||
<typeAlias alias="PropertyRoot" type="org.alfresco.repo.domain.propval.PropertyRootEntity"/>
|
<typeAlias alias="PropertyRoot" type="org.alfresco.repo.domain.propval.PropertyRootEntity"/>
|
||||||
<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="PropertyIdSearchRow" type="org.alfresco.repo.domain.propval.PropertyIdSearchRow"/>
|
<typeAlias alias="PropertyIdSearchRow" type="org.alfresco.repo.domain.propval.PropertyIdSearchRow"/>
|
||||||
|
|
||||||
<!-- -->
|
<!-- -->
|
||||||
@@ -74,6 +75,17 @@
|
|||||||
<result property="keyPropId" column="link_key_prop_id" jdbcType="BIGINT" javaType="long"/>
|
<result property="keyPropId" column="link_key_prop_id" jdbcType="BIGINT" javaType="long"/>
|
||||||
<result property="valuePropId" column="link_value_prop_id" jdbcType="BIGINT" javaType="long"/>
|
<result property="valuePropId" column="link_value_prop_id" jdbcType="BIGINT" javaType="long"/>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
<resultMap id="result_PropertyRoot" class="PropertyRoot">
|
||||||
|
<result property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
|
<result property="version" column="version" jdbcType="TINYINT" javaType="java.lang.Short"/>
|
||||||
|
</resultMap>
|
||||||
|
<resultMap id="result_PropertyUniqueContext" class="PropertyUniqueContext">
|
||||||
|
<result property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
|
<result property="version" column="version" jdbcType="TINYINT" javaType="java.lang.Short"/>
|
||||||
|
<result property="value1PropId" column="value1_prop_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
|
<result property="value2PropId" column="value2_prop_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
|
<result property="value3PropId" column="value3_prop_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
|
</resultMap>
|
||||||
<resultMap id="result_PropertyIdSearchRow" class="PropertyIdSearchRow">
|
<resultMap id="result_PropertyIdSearchRow" class="PropertyIdSearchRow">
|
||||||
<!-- If we use nested ResultMaps, then this ResultMap can't be embedded... -->
|
<!-- If we use nested ResultMaps, then this ResultMap can't be embedded... -->
|
||||||
<result property="rootPropId" column="link_root_prop_id" jdbcType="BIGINT" javaType="long"/>
|
<result property="rootPropId" column="link_root_prop_id" jdbcType="BIGINT" javaType="long"/>
|
||||||
@@ -134,6 +146,11 @@
|
|||||||
values (?)
|
values (?)
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
|
<sql id="insert_PropertyUniqueContext_AutoIncrement">
|
||||||
|
insert into alf_prop_unique_ctx (version, value1_prop_id, value2_prop_id, value3_prop_id)
|
||||||
|
values (#version#, #value1PropId#, #value2PropId#, #value3PropId#)
|
||||||
|
</sql>
|
||||||
|
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<!-- Statements -->
|
<!-- Statements -->
|
||||||
<!-- -->
|
<!-- -->
|
||||||
@@ -347,7 +364,7 @@
|
|||||||
pl.root_prop_id = #id#
|
pl.root_prop_id = #id#
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="select_PropertyRootById" parameterClass="PropertyRoot" resultClass="PropertyRoot">
|
<select id="select_PropertyRootById" parameterClass="PropertyRoot" resultMap="result_PropertyRoot">
|
||||||
select
|
select
|
||||||
id,
|
id,
|
||||||
version
|
version
|
||||||
@@ -394,4 +411,54 @@
|
|||||||
root_prop_id = #id#
|
root_prop_id = #id#
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
|
<select id="select_PropertyUniqueContextById" parameterClass="PropertyUniqueContext" resultMap="result_PropertyUniqueContext">
|
||||||
|
select
|
||||||
|
id,
|
||||||
|
version,
|
||||||
|
value1_prop_id,
|
||||||
|
value2_prop_id,
|
||||||
|
value3_prop_id
|
||||||
|
from
|
||||||
|
alf_prop_unique_ctx
|
||||||
|
where
|
||||||
|
id = #id#
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="select_PropertyUniqueContextByValues" parameterClass="PropertyUniqueContext" resultMap="result_PropertyUniqueContext">
|
||||||
|
select
|
||||||
|
id,
|
||||||
|
version,
|
||||||
|
value1_prop_id,
|
||||||
|
value2_prop_id,
|
||||||
|
value3_prop_id
|
||||||
|
from
|
||||||
|
alf_prop_unique_ctx
|
||||||
|
where
|
||||||
|
value1_prop_id = #value1PropId# and
|
||||||
|
value2_prop_id = #value2PropId# and
|
||||||
|
value3_prop_id = #value3PropId#
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<update id="update_PropertyUniqueContext" parameterClass="PropertyUniqueContext">
|
||||||
|
update
|
||||||
|
alf_prop_unique_ctx
|
||||||
|
set
|
||||||
|
version = #version#,
|
||||||
|
value1_prop_id = #value1PropId#,
|
||||||
|
value2_prop_id = #value2PropId#,
|
||||||
|
value3_prop_id = #value3PropId#
|
||||||
|
where
|
||||||
|
id = #id#
|
||||||
|
<isGreaterThan property="version" compareValue="1">
|
||||||
|
and version = ((#version#-1))
|
||||||
|
</isGreaterThan>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<delete id="delete_PropertyUniqueContextById" parameterClass="PropertyUniqueContext">
|
||||||
|
delete from
|
||||||
|
alf_prop_unique_ctx
|
||||||
|
where
|
||||||
|
id = #id#
|
||||||
|
</delete>
|
||||||
|
|
||||||
</sqlMap>
|
</sqlMap>
|
@@ -48,4 +48,11 @@
|
|||||||
</selectKey>
|
</selectKey>
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
|
<insert id="insert_PropertyUniqueContext" parameterClass="PropertyUniqueContext" >
|
||||||
|
<include refid="insert_PropertyUniqueContext_AutoIncrement"/>
|
||||||
|
<selectKey resultClass="long" keyProperty="id" type="post">
|
||||||
|
KEY_COLUMN:GENERATED_KEY
|
||||||
|
</selectKey>
|
||||||
|
</insert>
|
||||||
|
|
||||||
</sqlMap>
|
</sqlMap>
|
@@ -40,6 +40,7 @@ import org.alfresco.repo.cache.lookup.EntityLookupCache;
|
|||||||
import org.alfresco.repo.cache.lookup.EntityLookupCache.EntityLookupCallbackDAOAdaptor;
|
import org.alfresco.repo.cache.lookup.EntityLookupCache.EntityLookupCallbackDAOAdaptor;
|
||||||
import org.alfresco.repo.domain.CrcHelper;
|
import org.alfresco.repo.domain.CrcHelper;
|
||||||
import org.alfresco.repo.domain.propval.PropertyValueEntity.PersistedType;
|
import org.alfresco.repo.domain.propval.PropertyValueEntity.PersistedType;
|
||||||
|
import org.alfresco.repo.props.PropertyUniqueConstraintViolation;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
@@ -1059,6 +1060,102 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO
|
|||||||
*/
|
*/
|
||||||
protected abstract int deletePropertyLinks(Long rootPropId);
|
protected abstract int deletePropertyLinks(Long rootPropId);
|
||||||
|
|
||||||
|
//================================
|
||||||
|
// 'alf_prop_unique_ctx' accessors
|
||||||
|
//================================
|
||||||
|
|
||||||
|
public Long createPropertyUniqueContext(Serializable value1, Serializable value2, Serializable value3)
|
||||||
|
{
|
||||||
|
// Translate the properties. Null values are acceptable
|
||||||
|
Long id1 = getOrCreatePropertyValue(value1).getFirst();
|
||||||
|
Long id2 = getOrCreatePropertyValue(value2).getFirst();
|
||||||
|
Long id3 = getOrCreatePropertyValue(value3).getFirst();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PropertyUniqueContextEntity entity = createPropertyUniqueContext(id1, id2, id3);
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug(
|
||||||
|
"Created unique property context: \n" +
|
||||||
|
" Values: " + value1 + "-" + value2 + "-" + value3 + "\n" +
|
||||||
|
" Result: " + entity);
|
||||||
|
}
|
||||||
|
return entity.getId();
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
throw new PropertyUniqueConstraintViolation(value1, value2, value3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getPropertyUniqueContext(Serializable value1, Serializable value2, Serializable value3)
|
||||||
|
{
|
||||||
|
// Translate the properties. Null values are quite acceptable
|
||||||
|
Pair<Long, Serializable> pair1 = getPropertyValue(value1);
|
||||||
|
Pair<Long, Serializable> pair2 = getPropertyValue(value2);
|
||||||
|
Pair<Long, Serializable> pair3 = getPropertyValue(value3);
|
||||||
|
if (pair1 == null || pair2 == null || pair3 == null)
|
||||||
|
{
|
||||||
|
// None of the values exist so no unique context values can exist
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Long id1 = pair1.getFirst();
|
||||||
|
Long id2 = pair2.getFirst();
|
||||||
|
Long id3 = pair3.getFirst();
|
||||||
|
PropertyUniqueContextEntity entity = getPropertyUniqueContextByValues(id1, id2, id3);
|
||||||
|
// Done
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug(
|
||||||
|
"Searched for unique property context: \n" +
|
||||||
|
" Values: " + value1 + "-" + value2 + "-" + value3 + "\n" +
|
||||||
|
" Result: " + entity);
|
||||||
|
}
|
||||||
|
return entity == null ? null : entity.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updatePropertyUniqueContext(Long id, Serializable value1, Serializable value2, Serializable value3)
|
||||||
|
{
|
||||||
|
// Translate the properties. Null values are acceptable
|
||||||
|
Long id1 = getOrCreatePropertyValue(value1).getFirst();
|
||||||
|
Long id2 = getOrCreatePropertyValue(value2).getFirst();
|
||||||
|
Long id3 = getOrCreatePropertyValue(value3).getFirst();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PropertyUniqueContextEntity entity = getPropertyUniqueContextById(id);
|
||||||
|
if (entity == null)
|
||||||
|
{
|
||||||
|
throw new DataIntegrityViolationException("No unique property context exists for id: " + id);
|
||||||
|
}
|
||||||
|
entity.setValue1PropId(id1);
|
||||||
|
entity.setValue2PropId(id2);
|
||||||
|
entity.setValue3PropId(id3);
|
||||||
|
updatePropertyUniqueContext(entity);
|
||||||
|
// Done
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug(
|
||||||
|
"Updated unique property context: \n" +
|
||||||
|
" ID: " + id + "\n" +
|
||||||
|
" Values: " + value1 + "-" + value2 + "-" + value3);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
throw new PropertyUniqueConstraintViolation(value1, value2, value3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract PropertyUniqueContextEntity createPropertyUniqueContext(Long valueId1, Long valueId2, Long valueId3);
|
||||||
|
protected abstract PropertyUniqueContextEntity getPropertyUniqueContextById(Long id);
|
||||||
|
protected abstract PropertyUniqueContextEntity getPropertyUniqueContextByValues(Long valueId1, Long valueId2, Long valueId3);
|
||||||
|
protected abstract PropertyUniqueContextEntity updatePropertyUniqueContext(PropertyUniqueContextEntity entity);
|
||||||
|
|
||||||
|
//================================
|
||||||
|
// Utility methods
|
||||||
|
//================================
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Serializable convertPropertyIdSearchRows(List<PropertyIdSearchRow> rows)
|
public Serializable convertPropertyIdSearchRows(List<PropertyIdSearchRow> rows)
|
||||||
{
|
{
|
||||||
|
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity bean for <b>alf_prop_unique_ctx</b> table.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
public class PropertyUniqueContextEntity
|
||||||
|
{
|
||||||
|
private Long id;
|
||||||
|
private short version;
|
||||||
|
private Long value1PropId;
|
||||||
|
private Long value2PropId;
|
||||||
|
private Long value3PropId;
|
||||||
|
|
||||||
|
public PropertyUniqueContextEntity()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder(512);
|
||||||
|
sb.append("PropertyRootEntity")
|
||||||
|
.append("[ ID=").append(id)
|
||||||
|
.append(", version=").append(version)
|
||||||
|
.append(", value1PropId=").append(value1PropId)
|
||||||
|
.append(", value2PropId=").append(value2PropId)
|
||||||
|
.append(", value3PropId=").append(value3PropId)
|
||||||
|
.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void incrementVersion()
|
||||||
|
{
|
||||||
|
if (version >= Short.MAX_VALUE)
|
||||||
|
{
|
||||||
|
this.version = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.version++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id)
|
||||||
|
{
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getVersion()
|
||||||
|
{
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVersion(short version)
|
||||||
|
{
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getValue1PropId()
|
||||||
|
{
|
||||||
|
return value1PropId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue1PropId(Long value1PropId)
|
||||||
|
{
|
||||||
|
this.value1PropId = value1PropId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getValue2PropId()
|
||||||
|
{
|
||||||
|
return value2PropId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue2PropId(Long value2PropId)
|
||||||
|
{
|
||||||
|
this.value2PropId = value2PropId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getValue3PropId()
|
||||||
|
{
|
||||||
|
return value3PropId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue3PropId(Long value3PropId)
|
||||||
|
{
|
||||||
|
this.value3PropId = value3PropId;
|
||||||
|
}
|
||||||
|
}
|
@@ -29,6 +29,7 @@ import java.util.Date;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.alfresco.repo.domain.CrcHelper;
|
import org.alfresco.repo.domain.CrcHelper;
|
||||||
|
import org.alfresco.repo.props.PropertyUniqueConstraintViolation;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
import org.springframework.dao.DataIntegrityViolationException;
|
import org.springframework.dao.DataIntegrityViolationException;
|
||||||
|
|
||||||
@@ -255,6 +256,33 @@ public interface PropertyValueDAO
|
|||||||
*/
|
*/
|
||||||
void deleteProperty(Long id);
|
void deleteProperty(Long id);
|
||||||
|
|
||||||
|
//================================
|
||||||
|
// 'alf_prop_unique_ctx' accessors
|
||||||
|
//================================
|
||||||
|
/**
|
||||||
|
* <b>alf_prop_unique_ctx</b> accessor: find an existing unique context.
|
||||||
|
* <p/>
|
||||||
|
* The DAO ensures that the region-context-value combination will be globally unique.
|
||||||
|
*
|
||||||
|
* @throws PropertyUniqueConstraintViolation if the combination is not unique
|
||||||
|
*/
|
||||||
|
Long createPropertyUniqueContext(Serializable value1, Serializable value2, Serializable value3);
|
||||||
|
/**
|
||||||
|
* @see #createPropertyUniqueContext(Serializable, Serializable, Serializable)
|
||||||
|
*/
|
||||||
|
Long getPropertyUniqueContext(Serializable value1, Serializable value2, Serializable value3);
|
||||||
|
/**
|
||||||
|
* @see #createPropertyUniqueContext(Serializable, Serializable, Serializable)
|
||||||
|
*/
|
||||||
|
void updatePropertyUniqueContext(Long id, Serializable value1, Serializable value2, Serializable value3);
|
||||||
|
/**
|
||||||
|
* @see #createPropertyUniqueContext(Serializable, Serializable, Serializable)
|
||||||
|
*/
|
||||||
|
void deletePropertyUniqueContext(Long id);
|
||||||
|
|
||||||
|
//================================
|
||||||
|
// Utility methods
|
||||||
|
//================================
|
||||||
/**
|
/**
|
||||||
* Utility method to convert property query results into the original value. Note
|
* Utility method to convert property query results into the original value. Note
|
||||||
* that the rows must all share the same root property ID.
|
* that the rows must all share the same root property ID.
|
||||||
|
@@ -26,11 +26,9 @@ 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;
|
||||||
|
|
||||||
@@ -38,11 +36,13 @@ import javax.naming.CompositeName;
|
|||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
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;
|
||||||
import org.alfresco.service.ServiceRegistry;
|
import org.alfresco.service.ServiceRegistry;
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
import org.alfresco.util.ApplicationContextHelper;
|
import org.alfresco.util.ApplicationContextHelper;
|
||||||
|
import org.alfresco.util.GUID;
|
||||||
import org.alfresco.util.ISO8601DateFormat;
|
import org.alfresco.util.ISO8601DateFormat;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
import org.bouncycastle.util.Arrays;
|
import org.bouncycastle.util.Arrays;
|
||||||
@@ -589,29 +589,29 @@ public class PropertyValueDAOTest extends TestCase
|
|||||||
assertEquals(list, entityValueCheck);
|
assertEquals(list, entityValueCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testProperty_UpdateToVersionRollover() throws Exception
|
// public void testProperty_UpdateToVersionRollover() throws Exception
|
||||||
{
|
// {
|
||||||
final List<String> list = Collections.emptyList();
|
// final List<String> list = Collections.emptyList();
|
||||||
final Long propId = runPropertyTest((Serializable)list);
|
// final Long propId = runPropertyTest((Serializable)list);
|
||||||
|
//
|
||||||
// Do 1000 updates to a property
|
// // Do 1000 updates to a property
|
||||||
RetryingTransactionCallback<Void> updateThousandsCallback = new RetryingTransactionCallback<Void>()
|
// RetryingTransactionCallback<Void> updateThousandsCallback = new RetryingTransactionCallback<Void>()
|
||||||
{
|
// {
|
||||||
public Void execute() throws Throwable
|
// public Void execute() throws Throwable
|
||||||
{
|
// {
|
||||||
for (int i = 0; i < 1000; i++)
|
// for (int i = 0; i < 1000; i++)
|
||||||
{
|
// {
|
||||||
propertyValueDAO.updateProperty(propId, (Serializable)list);
|
// propertyValueDAO.updateProperty(propId, (Serializable)list);
|
||||||
}
|
// }
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
for (int i = 0; i < (Short.MAX_VALUE / 1000 + 1); i++)
|
// for (int i = 0; i < (Short.MAX_VALUE / 1000 + 1); i++)
|
||||||
{
|
// {
|
||||||
txnHelper.doInTransaction(updateThousandsCallback, false);
|
// txnHelper.doInTransaction(updateThousandsCallback, false);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
public void testProperty_Delete() throws Exception
|
public void testProperty_Delete() throws Exception
|
||||||
{
|
{
|
||||||
final ArrayList<String> list = new ArrayList<String>(20);
|
final ArrayList<String> list = new ArrayList<String>(20);
|
||||||
@@ -681,4 +681,63 @@ public class PropertyValueDAOTest extends TestCase
|
|||||||
removeCaches();
|
removeCaches();
|
||||||
testPropertySerializableValue();
|
testPropertySerializableValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testPropertyUniqueContext() throws Exception
|
||||||
|
{
|
||||||
|
final String aaa = GUID.generate();
|
||||||
|
final String bbb = GUID.generate();
|
||||||
|
RetryingTransactionCallback<Void> testCallback = new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
// Get the ID for nulls
|
||||||
|
Long nullId = propertyValueDAO.getPropertyUniqueContext(null, null, null);
|
||||||
|
if (nullId != null)
|
||||||
|
{
|
||||||
|
propertyValueDAO.deletePropertyUniqueContext(nullId);
|
||||||
|
}
|
||||||
|
// Check nulls
|
||||||
|
propertyValueDAO.createPropertyUniqueContext(null, null, null);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
propertyValueDAO.createPropertyUniqueContext(null, null, null);
|
||||||
|
fail("Failed to throw exception creating duplicate property unique context");
|
||||||
|
}
|
||||||
|
catch (PropertyUniqueConstraintViolation e)
|
||||||
|
{
|
||||||
|
// Expected
|
||||||
|
}
|
||||||
|
Long id = propertyValueDAO.createPropertyUniqueContext("A", "AA", aaa);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
propertyValueDAO.createPropertyUniqueContext("A", "AA", aaa);
|
||||||
|
fail("Failed to throw exception creating duplicate property unique context");
|
||||||
|
}
|
||||||
|
catch (PropertyUniqueConstraintViolation e)
|
||||||
|
{
|
||||||
|
// Expected
|
||||||
|
}
|
||||||
|
// Now update it
|
||||||
|
propertyValueDAO.updatePropertyUniqueContext(id, "A", "AA", bbb);
|
||||||
|
// Should be able to create the previous one ...
|
||||||
|
propertyValueDAO.createPropertyUniqueContext("A", "AA", aaa);
|
||||||
|
// ... and fail to create the second one
|
||||||
|
try
|
||||||
|
{
|
||||||
|
propertyValueDAO.createPropertyUniqueContext("A", "AA", bbb);
|
||||||
|
fail("Failed to throw exception creating duplicate property unique context");
|
||||||
|
}
|
||||||
|
catch (PropertyUniqueConstraintViolation e)
|
||||||
|
{
|
||||||
|
// Expected
|
||||||
|
}
|
||||||
|
// Delete
|
||||||
|
propertyValueDAO.deletePropertyUniqueContext(id);
|
||||||
|
propertyValueDAO.createPropertyUniqueContext("A", "AA", bbb);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
txnHelper.doInTransaction(testCallback, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -38,6 +38,7 @@ import org.alfresco.repo.domain.propval.PropertyRootEntity;
|
|||||||
import org.alfresco.repo.domain.propval.PropertySerializableValueEntity;
|
import org.alfresco.repo.domain.propval.PropertySerializableValueEntity;
|
||||||
import org.alfresco.repo.domain.propval.PropertyStringQueryEntity;
|
import org.alfresco.repo.domain.propval.PropertyStringQueryEntity;
|
||||||
import org.alfresco.repo.domain.propval.PropertyStringValueEntity;
|
import org.alfresco.repo.domain.propval.PropertyStringValueEntity;
|
||||||
|
import org.alfresco.repo.domain.propval.PropertyUniqueContextEntity;
|
||||||
import org.alfresco.repo.domain.propval.PropertyValueEntity;
|
import org.alfresco.repo.domain.propval.PropertyValueEntity;
|
||||||
import org.alfresco.repo.domain.propval.PropertyValueEntity.PersistedType;
|
import org.alfresco.repo.domain.propval.PropertyValueEntity.PersistedType;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
@@ -81,6 +82,13 @@ public class PropertyValueDAOImpl extends AbstractPropertyValueDAOImpl
|
|||||||
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";
|
||||||
private static final String DELETE_PROPERTY_ROOT_BY_ID = "alfresco.propval.delete_PropertyRootById";
|
private static final String DELETE_PROPERTY_ROOT_BY_ID = "alfresco.propval.delete_PropertyRootById";
|
||||||
|
|
||||||
|
private static final String SELECT_PROPERTY_UNIQUE_CTX_BY_ID = "alfresco.propval.select_PropertyUniqueContextById";
|
||||||
|
private static final String SELECT_PROPERTY_UNIQUE_CTX_BY_VALUES = "alfresco.propval.select_PropertyUniqueContextByValues";
|
||||||
|
private static final String INSERT_PROPERTY_UNIQUE_CTX = "alfresco.propval.insert_PropertyUniqueContext";
|
||||||
|
private static final String UPDATE_PROPERTY_UNIQUE_CTX = "alfresco.propval.update_PropertyUniqueContext";
|
||||||
|
private static final String DELETE_PROPERTY_UNIQUE_CTX_BY_ID = "alfresco.propval.delete_PropertyUniqueContextById";
|
||||||
|
|
||||||
private static final String INSERT_PROPERTY_LINK = "alfresco.propval.insert_PropertyLink";
|
private static final String INSERT_PROPERTY_LINK = "alfresco.propval.insert_PropertyLink";
|
||||||
private static final String DELETE_PROPERTY_LINKS_BY_ROOT_ID = "alfresco.propval.delete_PropertyLinksByRootId";
|
private static final String DELETE_PROPERTY_LINKS_BY_ROOT_ID = "alfresco.propval.delete_PropertyLinksByRootId";
|
||||||
|
|
||||||
@@ -478,6 +486,53 @@ public class PropertyValueDAOImpl extends AbstractPropertyValueDAOImpl
|
|||||||
template.delete(DELETE_PROPERTY_ROOT_BY_ID, entity);
|
template.delete(DELETE_PROPERTY_ROOT_BY_ID, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PropertyUniqueContextEntity createPropertyUniqueContext(Long valueId1, Long valueId2, Long valueId3)
|
||||||
|
{
|
||||||
|
PropertyUniqueContextEntity entity = new PropertyUniqueContextEntity();
|
||||||
|
entity.setValue1PropId(valueId1);
|
||||||
|
entity.setValue2PropId(valueId2);
|
||||||
|
entity.setValue3PropId(valueId3);
|
||||||
|
Long id = (Long) template.insert(INSERT_PROPERTY_UNIQUE_CTX, entity);
|
||||||
|
entity.setId(id);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PropertyUniqueContextEntity getPropertyUniqueContextById(Long id)
|
||||||
|
{
|
||||||
|
PropertyUniqueContextEntity entity = new PropertyUniqueContextEntity();
|
||||||
|
entity.setId(id);
|
||||||
|
entity = (PropertyUniqueContextEntity) template.queryForObject(SELECT_PROPERTY_UNIQUE_CTX_BY_ID, entity);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PropertyUniqueContextEntity getPropertyUniqueContextByValues(Long valueId1, Long valueId2, Long valueId3)
|
||||||
|
{
|
||||||
|
PropertyUniqueContextEntity entity = new PropertyUniqueContextEntity();
|
||||||
|
entity.setValue1PropId(valueId1);
|
||||||
|
entity.setValue2PropId(valueId2);
|
||||||
|
entity.setValue3PropId(valueId3);
|
||||||
|
entity = (PropertyUniqueContextEntity) template.queryForObject(SELECT_PROPERTY_UNIQUE_CTX_BY_VALUES, entity);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PropertyUniqueContextEntity updatePropertyUniqueContext(PropertyUniqueContextEntity entity)
|
||||||
|
{
|
||||||
|
entity.incrementVersion();
|
||||||
|
template.update(UPDATE_PROPERTY_UNIQUE_CTX, entity, 1);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deletePropertyUniqueContext(Long id)
|
||||||
|
{
|
||||||
|
PropertyUniqueContextEntity entity = new PropertyUniqueContextEntity();
|
||||||
|
entity.setId(id);
|
||||||
|
template.delete(DELETE_PROPERTY_UNIQUE_CTX_BY_ID, entity);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void createPropertyLink(
|
protected void createPropertyLink(
|
||||||
Long rootPropId,
|
Long rootPropId,
|
||||||
|
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* 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.props;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception generated when the {@link PropertyValueDAO}
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
public class PropertyUniqueConstraintViolation extends AlfrescoRuntimeException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = -7792036870731759068L;
|
||||||
|
|
||||||
|
private final Serializable value1;
|
||||||
|
private final Serializable value2;
|
||||||
|
private final Serializable value3;
|
||||||
|
|
||||||
|
public PropertyUniqueConstraintViolation(Serializable value1, Serializable value2, Serializable value3)
|
||||||
|
{
|
||||||
|
super("Non-unique values for unique constraint: " + value1 + "-" + value2 + "-" + value3);
|
||||||
|
this.value1 = value1;
|
||||||
|
this.value2 = value2;
|
||||||
|
this.value3 = value3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Serializable getValue1()
|
||||||
|
{
|
||||||
|
return value1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Serializable getValue2()
|
||||||
|
{
|
||||||
|
return value2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Serializable getValue3()
|
||||||
|
{
|
||||||
|
return value3;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user