diff --git a/config/alfresco/dbscripts/create/3.3/org.hibernate.dialect.MySQLInnoDBDialect/AlfrescoPostCreate-3.3-PropertyValueTables.sql b/config/alfresco/dbscripts/create/3.3/org.hibernate.dialect.MySQLInnoDBDialect/AlfrescoPostCreate-3.3-PropertyValueTables.sql index 3937309b77..b0f12d0cc7 100644 --- a/config/alfresco/dbscripts/create/3.3/org.hibernate.dialect.MySQLInnoDBDialect/AlfrescoPostCreate-3.3-PropertyValueTables.sql +++ b/config/alfresco/dbscripts/create/3.3/org.hibernate.dialect.MySQLInnoDBDialect/AlfrescoPostCreate-3.3-PropertyValueTables.sql @@ -10,7 +10,6 @@ CREATE TABLE alf_prop_class ( id BIGINT NOT NULL AUTO_INCREMENT, - version BIGINT NOT NULL, java_class_name VARCHAR(255) NOT NULL, java_class_name_short VARCHAR(32) NOT NULL, java_class_name_crc BIGINT NOT NULL, @@ -19,6 +18,24 @@ CREATE TABLE alf_prop_class PRIMARY KEY (id) ) ENGINE=InnoDB; +CREATE TABLE alf_prop_string_value +( + id BIGINT NOT NULL AUTO_INCREMENT, + string_value text NOT NULL, + INDEX idx_prop_str_val (string_value(64)), + PRIMARY KEY (id) +) ENGINE=InnoDB; + +--CREATE TABLE alf_prop_string_value +--( +-- id BIGINT NOT NULL AUTO_INCREMENT, +-- string_value text NOT NULL, +-- prop_class_id BIGINT NOT NULL, +-- INDEX idx_prop_str_val (string_value(64)), +-- CONSTRAINT fk_prop_str_classid FOREIGN KEY (prop_class_id) REFERENCES alf_prop_class (id), +-- PRIMARY KEY (id) +--) ENGINE=InnoDB; + -- -- Record script finish -- diff --git a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/propval-common-SqlMap.xml b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/propval-common-SqlMap.xml index 91be74448c..314b20fd91 100644 --- a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/propval-common-SqlMap.xml +++ b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/propval-common-SqlMap.xml @@ -11,6 +11,7 @@ + @@ -18,11 +19,14 @@ - + + + + @@ -43,8 +47,13 @@ - insert into alf_prop_class (version, java_class_name, java_class_name_short, java_class_name_crc) - values (#version#, #javaClassName#, #javaClassNameShort#, #javaClassNameCrc#) + insert into alf_prop_class (java_class_name, java_class_name_short, java_class_name_crc) + values (#javaClassName#, #javaClassNameShort#, #javaClassNameCrc#) + + + + insert into alf_prop_string_value (string_value) + values (#stringValue#) @@ -72,4 +81,24 @@ java_class_name_short = #javaClassNameShort# + + + + + + \ No newline at end of file diff --git a/config/alfresco/ibatis/org.hibernate.dialect.MySQLInnoDBDialect/propval-insert-SqlMap.xml b/config/alfresco/ibatis/org.hibernate.dialect.MySQLInnoDBDialect/propval-insert-SqlMap.xml index 6eb4a28c5d..d51a6afb57 100644 --- a/config/alfresco/ibatis/org.hibernate.dialect.MySQLInnoDBDialect/propval-insert-SqlMap.xml +++ b/config/alfresco/ibatis/org.hibernate.dialect.MySQLInnoDBDialect/propval-insert-SqlMap.xml @@ -13,4 +13,11 @@ + + + + KEY_COLUMN:GENERATED_KEY + + + \ No newline at end of file diff --git a/source/java/org/alfresco/repo/cache/lookup/EntityLookupCache.java b/source/java/org/alfresco/repo/cache/lookup/EntityLookupCache.java index 6c9b28817a..47af7166eb 100644 --- a/source/java/org/alfresco/repo/cache/lookup/EntityLookupCache.java +++ b/source/java/org/alfresco/repo/cache/lookup/EntityLookupCache.java @@ -28,10 +28,12 @@ import java.io.Serializable; import org.alfresco.repo.cache.SimpleCache; import org.alfresco.util.Pair; +import org.alfresco.util.ParameterCheck; /** * A cache for two-way lookups of database entities. These are characterized by having a unique - * key (perhaps a database ID) and a separate unique key that identifies the object. + * key (perhaps a database ID) and a separate unique key that identifies the object. If no cache + * is given, then all calls are passed through to the backing DAO. *

* The keys must have good equals and hashCode implementations and * must respect the case-sensitivity of the use-case. @@ -90,6 +92,17 @@ public class EntityLookupCache entityLookup; private final String cacheRegion; + /** + * Construct the lookup cache without any cache. All calls are passed directly to the + * underlying DAO entity lookup. + * + * @param entityLookup the instance that is able to find and persist entities + */ + public EntityLookupCache(EntityLookupCallbackDAO entityLookup) + { + this(null, CACHE_REGION_DEFAULT, entityLookup); + } + /** * Construct the lookup cache, using the {@link #CACHE_REGION_DEFAULT default cache region}. * @@ -108,21 +121,30 @@ public class EntityLookupCachenull to have no backing + * in a cache. * @param cacheRegion the region within the cache to use. * @param entityLookup the instance that is able to find and persist entities */ @SuppressWarnings("unchecked") public EntityLookupCache(SimpleCache cache, String cacheRegion, EntityLookupCallbackDAO entityLookup) { + ParameterCheck.mandatory("cacheRegion", cacheRegion); + ParameterCheck.mandatory("entityLookup", entityLookup); this.cache = cache; - this.entityLookup = entityLookup; this.cacheRegion = cacheRegion; + this.entityLookup = entityLookup; } @SuppressWarnings("unchecked") public Pair getByKey(K key) { + // Handle missing cache + if (cache == null) + { + return entityLookup.findByKey(key); + } + CacheRegionKey cacheKey = new CacheRegionKey(cacheRegion, key); // Look in the cache V value = (V) cache.get(cacheKey); @@ -154,6 +176,12 @@ public class EntityLookupCache getByValue(V value) { + // Handle missing cache + if (cache == null) + { + return entityLookup.findByValue(value); + } + // Get the value key VK valueKey = entityLookup.getValueKey(value); CacheRegionKey cacheKey = new CacheRegionKey(cacheRegion, valueKey); @@ -189,6 +217,17 @@ public class EntityLookupCache getOrCreateByValue(V value) { + // Handle missing cache + if (cache == null) + { + Pair entityPair = entityLookup.findByValue(value); + if (entityPair == null) + { + entityPair = entityLookup.createValue(value); + } + return entityPair; + } + // Get the value key VK valueKey = entityLookup.getValueKey(value); CacheRegionKey cacheKey = new CacheRegionKey(cacheRegion, valueKey); diff --git a/source/java/org/alfresco/repo/domain/propval/AbstractPropertyValueDAOImpl.java b/source/java/org/alfresco/repo/domain/propval/AbstractPropertyValueDAOImpl.java index b9178837d3..4cc26248cc 100644 --- a/source/java/org/alfresco/repo/domain/propval/AbstractPropertyValueDAOImpl.java +++ b/source/java/org/alfresco/repo/domain/propval/AbstractPropertyValueDAOImpl.java @@ -30,6 +30,7 @@ import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.repo.cache.SimpleCache; import org.alfresco.repo.cache.lookup.EntityLookupCache; import org.alfresco.repo.cache.lookup.EntityLookupCache.EntityLookupCallbackDAO; +import org.alfresco.repo.domain.CrcHelper; import org.alfresco.util.Pair; /** @@ -44,20 +45,69 @@ import org.alfresco.util.Pair; public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO { private static final String CACHE_REGION_PROPERTY_CLASS = "PropertyClass"; + private static final String CACHE_REGION_PROPERTY_STRING_VALUE = "PropertyStringValue"; + + private final PropertyClassCallbackDAO propertyClassDaoCallback; + private final PropertyStringValueCallbackDAO propertyStringValueCallback; + /** + * Cache for the property class:
+ * KEY: ID
+ * VALUE: Java class
+ * VALUE KEY: Java class name
+ */ private EntityLookupCache, String> propertyClassCache; + /** + * Cache for the property string value:
+ * KEY: ID
+ * VALUE: The full string
+ * VALUE KEY: Short string-crc pair ({@link CrcHelper#getStringCrcPair(String, int, boolean, boolean)})
+ */ + private EntityLookupCache> propertyStringValueCache; /** + * Default constructor. + *

+ * This sets up the DAO accessors to bypass any caching to handle the case where the caches are not + * supplied in the setters. + */ + public AbstractPropertyValueDAOImpl() + { + this.propertyClassDaoCallback = new PropertyClassCallbackDAO(); + this.propertyStringValueCallback = new PropertyStringValueCallbackDAO(); + + this.propertyClassCache = new EntityLookupCache, String>(propertyClassDaoCallback); + this.propertyStringValueCache = new EntityLookupCache>(propertyStringValueCallback); + } + + /** + * Set the cache to use for alf_prop_class lookups (optional). * * @param propertyClassCache the cache of IDs to property classes */ public void setPropertyClassCache(SimpleCache propertyClassCache) { - PropertyValueCallbackDAO daoCallback = new PropertyValueCallbackDAO(); this.propertyClassCache = new EntityLookupCache, String>( propertyClassCache, CACHE_REGION_PROPERTY_CLASS, - daoCallback); + propertyClassDaoCallback); } + + /** + * Set the cache to use for alf_prop_string_value lookups (optional). + * + * @param propertyStringValueCache the cache of IDs to property string values + */ + public void setPropertyStringValueCache(SimpleCache propertyStringValueCache) + { + this.propertyStringValueCache = new EntityLookupCache>( + propertyStringValueCache, + CACHE_REGION_PROPERTY_STRING_VALUE, + propertyStringValueCallback); + } + + //================================ + // 'alf_prop_class' accessors + //================================ public Pair> getPropertyClass(Long id) { @@ -69,22 +119,22 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO return entityPair; } - public Pair> getPropertyClass(Class clazz) + public Pair> getPropertyClass(Class value) { - Pair> entityPair = propertyClassCache.getByValue(clazz); + Pair> entityPair = propertyClassCache.getByValue(value); return entityPair; } - public Pair> getOrCreatePropertyClass(Class clazz) + public Pair> getOrCreatePropertyClass(Class value) { - Pair> entityPair = propertyClassCache.getOrCreateByValue(clazz); + Pair> entityPair = propertyClassCache.getOrCreateByValue(value); return entityPair; } /** - * Callback for alf_prop_type DAO. + * Callback for alf_prop_class DAO. */ - private class PropertyValueCallbackDAO implements EntityLookupCallbackDAO, String> + private class PropertyClassCallbackDAO implements EntityLookupCallbackDAO, String> { private final Pair> convertEntityToPair(PropertyClassEntity propertyClassEntity) { @@ -105,24 +155,96 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO public Pair> createValue(Class value) { - PropertyClassEntity propertyClassEntity = createClass(value); - return convertEntityToPair(propertyClassEntity); + PropertyClassEntity entity = createClass(value); + return convertEntityToPair(entity); } public Pair> findByKey(Long key) { - PropertyClassEntity propertyClassEntity = findClassById(key); - return convertEntityToPair(propertyClassEntity); + PropertyClassEntity entity = findClassById(key); + return convertEntityToPair(entity); } public Pair> findByValue(Class value) { - PropertyClassEntity propertyClassEntity = findClassByValue(value); - return convertEntityToPair(propertyClassEntity); + PropertyClassEntity entity = findClassByValue(value); + return convertEntityToPair(entity); } } - protected abstract PropertyClassEntity createClass(Class value); protected abstract PropertyClassEntity findClassById(Long id); protected abstract PropertyClassEntity findClassByValue(Class value); + protected abstract PropertyClassEntity createClass(Class value); + + //================================ + // 'alf_prop_string_value' accessors + //================================ + + public Pair getPropertyStringValue(Long id) + { + Pair entityPair = propertyStringValueCache.getByKey(id); + if (entityPair == null) + { + throw new AlfrescoRuntimeException("No property class exists for ID " + id); + } + return entityPair; + } + + public Pair getPropertyStringValue(String value) + { + Pair entityPair = propertyStringValueCache.getByValue(value); + return entityPair; + } + + public Pair getOrCreatePropertyStringValue(String value) + { + Pair entityPair = propertyStringValueCache.getOrCreateByValue(value); + return entityPair; + } + + /** + * Callback for alf_prop_string_value DAO. + */ + private class PropertyStringValueCallbackDAO implements EntityLookupCallbackDAO> + { + private final Pair convertEntityToPair(PropertyStringValueEntity propertyStringValueEntity) + { + if (propertyStringValueEntity == null) + { + return null; + } + else + { + return propertyStringValueEntity.getEntityPair(); + } + } + + public Pair getValueKey(String value) + { + return CrcHelper.getStringCrcPair(value, 128, true, true); + } + + public Pair createValue(String value) + { + PropertyStringValueEntity entity = createStringValue(value); + return convertEntityToPair(entity); + } + + public Pair findByKey(Long key) + { + PropertyStringValueEntity entity = findStringValueById(key); + return convertEntityToPair(entity); + } + + public Pair findByValue(String value) + { + PropertyStringValueEntity entity = findStringValueByValue(value); + return convertEntityToPair(entity); + } + } + + protected abstract PropertyStringValueEntity findStringValueById(Long id); + protected abstract PropertyStringValueEntity findStringValueByValue(String value); + protected abstract PropertyStringValueEntity createStringValue(String value); + } diff --git a/source/java/org/alfresco/repo/domain/propval/PropertyClassEntity.java b/source/java/org/alfresco/repo/domain/propval/PropertyClassEntity.java index 5329336289..35c5a77260 100644 --- a/source/java/org/alfresco/repo/domain/propval/PropertyClassEntity.java +++ b/source/java/org/alfresco/repo/domain/propval/PropertyClassEntity.java @@ -37,11 +37,7 @@ import org.alfresco.util.Pair; */ public class PropertyClassEntity { - public static final Long CONST_LONG_ZERO = new Long(0L); - public static final String EMPTY_URL = "empty"; - private Long id; - private Long version; private Class javaClass; private String javaClassName; private String javaClassNameShort; @@ -121,16 +117,6 @@ public class PropertyClassEntity this.id = id; } - public Long getVersion() - { - return version; - } - - public void setVersion(Long version) - { - this.version = version; - } - public void setJavaClass(Class javaClass) { this.javaClass = javaClass; diff --git a/source/java/org/alfresco/repo/domain/propval/PropertyStringValueEntity.java b/source/java/org/alfresco/repo/domain/propval/PropertyStringValueEntity.java new file mode 100644 index 0000000000..f1ba4afb99 --- /dev/null +++ b/source/java/org/alfresco/repo/domain/propval/PropertyStringValueEntity.java @@ -0,0 +1,104 @@ +/* + * 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 org.alfresco.util.EqualsHelper; +import org.alfresco.util.Pair; + +/** + * Entity bean for alf_prop_string_value table. + * + * @author Derek Hulley + * @since 3.3 + */ +public class PropertyStringValueEntity +{ + private Long id; + private String stringValue; + + public PropertyStringValueEntity() + { + } + + @Override + public int hashCode() + { + return (stringValue == null ? 0 : stringValue.hashCode()); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + else if (obj != null && obj instanceof PropertyStringValueEntity) + { + PropertyStringValueEntity that = (PropertyStringValueEntity) obj; + return EqualsHelper.nullSafeEquals(this.stringValue, that.stringValue); + } + else + { + return false; + } + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(512); + sb.append("PropertyStringValueEntity") + .append("[ ID=").append(id) + .append(", stringValue=").append(stringValue) + .append("]"); + return sb.toString(); + } + + public Pair getEntityPair() + { + return new Pair(id, stringValue); + } + + public Long getId() + { + return id; + } + + public void setId(Long id) + { + this.id = id; + } + + public String getStringValue() + { + return stringValue; + } + + public void setStringValue(String stringValue) + { + this.stringValue = stringValue; + } +} diff --git a/source/java/org/alfresco/repo/domain/propval/PropertyValueDAO.java b/source/java/org/alfresco/repo/domain/propval/PropertyValueDAO.java index cebb8e18c0..afb0f3c913 100644 --- a/source/java/org/alfresco/repo/domain/propval/PropertyValueDAO.java +++ b/source/java/org/alfresco/repo/domain/propval/PropertyValueDAO.java @@ -34,9 +34,33 @@ import org.alfresco.util.Pair; */ public interface PropertyValueDAO { - Pair> getPropertyClass(Class clazz); - + /** + * alf_prop_class accessor + */ Pair> getPropertyClass(Long id); - Pair> getOrCreatePropertyClass(Class clazz); + /** + * alf_prop_class accessor + */ + Pair> getPropertyClass(Class value); + + /** + * alf_prop_class accessor + */ + Pair> getOrCreatePropertyClass(Class value); + + /** + * alf_prop_string_value accessor + */ + Pair getPropertyStringValue(Long id); + + /** + * alf_prop_string_value accessor + */ + Pair getPropertyStringValue(String value); + + /** + * alf_prop_string_value accessor + */ + Pair getOrCreatePropertyStringValue(String value); } diff --git a/source/java/org/alfresco/repo/domain/propval/PropertyValueDAOTest.java b/source/java/org/alfresco/repo/domain/propval/PropertyValueDAOTest.java index ef17f75d6f..af955df2c5 100644 --- a/source/java/org/alfresco/repo/domain/propval/PropertyValueDAOTest.java +++ b/source/java/org/alfresco/repo/domain/propval/PropertyValueDAOTest.java @@ -118,4 +118,54 @@ public class PropertyValueDAOTest extends TestCase }; txnHelper.doInTransaction(noHitCallback, false); } + + public void testPropertyStringValue() throws Exception + { + final String stringValue = "One Two Three"; + final String stringValueUpper = stringValue.toUpperCase(); + final String stringValueLower = stringValue.toLowerCase(); + RetryingTransactionCallback> createStringCallback = new RetryingTransactionCallback>() + { + public Pair execute() throws Throwable + { + // Get the classes + return propertyValueDAO.getOrCreatePropertyStringValue(stringValue); + } + }; + final Pair stringEntityPair = txnHelper.doInTransaction(createStringCallback, false); + assertNotNull(stringEntityPair); + assertNotNull(stringEntityPair.getFirst()); + assertEquals(stringValue, stringEntityPair.getSecond()); + + // Check that the uppercase and lowercase strings don't have entries + RetryingTransactionCallback getClassCallback = new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + Pair checkPair1 = propertyValueDAO.getPropertyStringValue(stringValue); + assertNotNull(checkPair1); + assertEquals(stringValue, checkPair1.getSecond()); + Pair checkPair2 = propertyValueDAO.getPropertyStringValue(stringValueUpper); + assertNull(checkPair2); + Pair checkPair3 = propertyValueDAO.getPropertyStringValue(stringValueLower); + assertNull(checkPair3); + return null; + } + }; + txnHelper.doInTransaction(getClassCallback, true); + + RetryingTransactionCallback> createStringUpperCallback = new RetryingTransactionCallback>() + { + public Pair execute() throws Throwable + { + // Get the classes + return propertyValueDAO.getOrCreatePropertyStringValue(stringValueUpper); + } + }; + final Pair stringUpperEntityPair = txnHelper.doInTransaction(createStringUpperCallback, false); + assertNotNull(stringUpperEntityPair); + assertNotNull(stringUpperEntityPair.getFirst()); + assertEquals(stringValueUpper, stringUpperEntityPair.getSecond()); + assertNotSame("String IDs were not different", stringEntityPair.getFirst(), stringUpperEntityPair.getFirst()); + } } diff --git a/source/java/org/alfresco/repo/domain/propval/ibatis/PropertyValueDAOImpl.java b/source/java/org/alfresco/repo/domain/propval/ibatis/PropertyValueDAOImpl.java index 137be1c5de..5290efddad 100644 --- a/source/java/org/alfresco/repo/domain/propval/ibatis/PropertyValueDAOImpl.java +++ b/source/java/org/alfresco/repo/domain/propval/ibatis/PropertyValueDAOImpl.java @@ -24,8 +24,11 @@ */ package org.alfresco.repo.domain.propval.ibatis; +import java.util.List; + import org.alfresco.repo.domain.propval.AbstractPropertyValueDAOImpl; import org.alfresco.repo.domain.propval.PropertyClassEntity; +import org.alfresco.repo.domain.propval.PropertyStringValueEntity; import org.springframework.orm.ibatis.SqlMapClientTemplate; /** @@ -40,6 +43,9 @@ public class PropertyValueDAOImpl extends AbstractPropertyValueDAOImpl private static final String SELECT_PROPERTY_CLASS_BY_ID = "select.PropertyClassByID"; private static final String SELECT_PROPERTY_CLASS_BY_NAME = "select.PropertyClassByName"; private static final String INSERT_PROPERTY_CLASS = "insert.PropertyClass"; + private static final String SELECT_PROPERTY_STRING_VALUE_BY_ID = "select.PropertyStringValueByID"; + private static final String SELECT_PROPERTY_STRING_VALUE_BY_STRING = "select.PropertyStringValueByString"; + private static final String INSERT_PROPERTY_STRING_VALUE = "insert.PropertyStringValue"; private SqlMapClientTemplate template; @@ -51,32 +57,72 @@ public class PropertyValueDAOImpl extends AbstractPropertyValueDAOImpl @Override protected PropertyClassEntity findClassById(Long id) { - PropertyClassEntity propertyClassEntity = new PropertyClassEntity(); - propertyClassEntity.setId(id); - propertyClassEntity = (PropertyClassEntity) template.queryForObject(SELECT_PROPERTY_CLASS_BY_ID, propertyClassEntity); + PropertyClassEntity entity = new PropertyClassEntity(); + entity.setId(id); + entity = (PropertyClassEntity) template.queryForObject(SELECT_PROPERTY_CLASS_BY_ID, entity); // Done - return propertyClassEntity; + return entity; } @Override protected PropertyClassEntity findClassByValue(Class value) { - PropertyClassEntity propertyClassEntity = new PropertyClassEntity(); - propertyClassEntity.setJavaClass(value); - propertyClassEntity = (PropertyClassEntity) template.queryForObject(SELECT_PROPERTY_CLASS_BY_NAME, propertyClassEntity); + PropertyClassEntity entity = new PropertyClassEntity(); + entity.setJavaClass(value); + entity = (PropertyClassEntity) template.queryForObject(SELECT_PROPERTY_CLASS_BY_NAME, entity); // Done - return propertyClassEntity; + return entity; } @Override protected PropertyClassEntity createClass(Class value) { - PropertyClassEntity propertyClassEntity = new PropertyClassEntity(); - propertyClassEntity.setJavaClass(value); - propertyClassEntity.setVersion(VERSION_ONE); - Long id = (Long) template.insert(INSERT_PROPERTY_CLASS, propertyClassEntity); - propertyClassEntity.setId(id); + PropertyClassEntity entity = new PropertyClassEntity(); + entity.setJavaClass(value); + Long id = (Long) template.insert(INSERT_PROPERTY_CLASS, entity); + entity.setId(id); // Done - return propertyClassEntity; + return entity; + } + + @Override + protected PropertyStringValueEntity findStringValueById(Long id) + { + PropertyStringValueEntity entity = new PropertyStringValueEntity(); + entity.setId(id); + entity = (PropertyStringValueEntity) template.queryForObject(SELECT_PROPERTY_STRING_VALUE_BY_ID, entity); + // Done + return entity; + } + + @SuppressWarnings("unchecked") + @Override + protected PropertyStringValueEntity findStringValueByValue(String value) + { + PropertyStringValueEntity entity = new PropertyStringValueEntity(); + entity.setStringValue(value); + List results = (List) template.queryForList(SELECT_PROPERTY_STRING_VALUE_BY_STRING, entity); + // There are several matches, so find the first one that matches exactly + for (PropertyStringValueEntity resultEntity : results) + { + if (value.equals(resultEntity.getStringValue())) + { + // Found a match + return resultEntity; + } + } + // No real match + return null; + } + + @Override + protected PropertyStringValueEntity createStringValue(String value) + { + PropertyStringValueEntity entity = new PropertyStringValueEntity(); + entity.setStringValue(value); + Long id = (Long) template.insert(INSERT_PROPERTY_STRING_VALUE, entity); + entity.setId(id); + // Done + return entity; } }