DATAGRAPH-433: Begin fixing of how uniquely indexed properties are handled
This commit is contained in:
committed by
Michael Hunger
parent
48ab04c3da
commit
36c951e55d
@@ -19,7 +19,7 @@ package org.springframework.data.neo4j.rest.integration;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.data.neo4j.rest.support.RestTestBase;
|
||||
import org.springframework.data.neo4j.unique.UniqueEntityTests;
|
||||
import org.springframework.data.neo4j.unique.legacy.UniqueLegacyIndexBasedEntityTests;
|
||||
import org.springframework.test.context.CleanContextCacheTestExecutionListener;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestExecutionListeners;
|
||||
@@ -33,10 +33,10 @@ import org.springframework.test.context.transaction.TransactionalTestExecutionLi
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = {
|
||||
"classpath:unique-test-context.xml",
|
||||
"classpath:unique-legacy-test-context.xml",
|
||||
"classpath:RestTests-context.xml"})
|
||||
@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
|
||||
public class RestUniqueEntityTests extends UniqueEntityTests {
|
||||
public class RestUniqueEntityTests extends UniqueLegacyIndexBasedEntityTests {
|
||||
|
||||
@BeforeClass
|
||||
public static void startDb() throws Exception {
|
||||
|
||||
@@ -39,10 +39,10 @@ public class NodeDelegatingFieldAccessorFactory extends DelegatingFieldAccessorF
|
||||
template,
|
||||
new PropertyFieldAccessorFactory(template),
|
||||
new ConvertingNodePropertyFieldAccessorFactory(template)),
|
||||
new SchemaIndexingPropertyFieldAccessorListenerFactory(
|
||||
/*new SchemaIndexingPropertyFieldAccessorListenerFactory(
|
||||
template,
|
||||
new PropertyFieldAccessorFactory(template),
|
||||
new ConvertingNodePropertyFieldAccessorFactory(template)),
|
||||
new ConvertingNodePropertyFieldAccessorFactory(template)), */
|
||||
new ValidatingNodePropertyFieldAccessorListenerFactory(template)
|
||||
);
|
||||
}
|
||||
@@ -53,6 +53,7 @@ public class NodeDelegatingFieldAccessorFactory extends DelegatingFieldAccessorF
|
||||
new IdFieldAccessorFactory(template),
|
||||
new TransientFieldAccessorFactory(),
|
||||
//TODO Labels new LabelFieldAccessorFactory(template),
|
||||
new SchemaIndexingFieldAccessorFactory(template),
|
||||
new TraversalFieldAccessorFactory(template),
|
||||
new QueryFieldAccessorFactory(template),
|
||||
new PropertyFieldAccessorFactory(template),
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j.fieldaccess;
|
||||
|
||||
|
||||
import org.neo4j.graphdb.DynamicLabel;
|
||||
import org.neo4j.graphdb.Label;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.PropertyContainer;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.neo4j.mapping.MappingPolicy;
|
||||
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
|
||||
import org.springframework.data.neo4j.support.Neo4jTemplate;
|
||||
import org.springframework.data.neo4j.support.mapping.StoredEntityType;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import static org.springframework.data.neo4j.support.DoReturn.doReturn;
|
||||
|
||||
/**
|
||||
* @author Nicki Watt
|
||||
* @since 01.03.2014
|
||||
*/
|
||||
public class SchemaIndexingFieldAccessorFactory implements FieldAccessorFactory {
|
||||
private final Neo4jTemplate template;
|
||||
|
||||
public SchemaIndexingFieldAccessorFactory(Neo4jTemplate template) {
|
||||
this.template = template;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(final Neo4jPersistentProperty property) {
|
||||
return property.isIndexed() && property.getIndexInfo().isLabelBased();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldAccessor forField(final Neo4jPersistentProperty property) {
|
||||
return new SchemaIndexedFieldAccessor(template,property);
|
||||
}
|
||||
|
||||
public static class SchemaIndexedFieldAccessor extends PropertyFieldAccessorFactory.PropertyFieldAccessor {
|
||||
|
||||
public SchemaIndexedFieldAccessor(Neo4jTemplate template,Neo4jPersistentProperty property) {
|
||||
super(template,property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWriteable(Object entity) {
|
||||
return super.isWriteable(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(final Object entity, final Object newVal, MappingPolicy mappingPolicy) {
|
||||
final PropertyContainer state = template.getPersistentState(entity);
|
||||
if (!(state instanceof Node)) {
|
||||
throw new IllegalArgumentException("not expecting to deal with non node property");
|
||||
}
|
||||
|
||||
applyMissingSchemaIndexLabels(entity,(Node)state);
|
||||
checkForUniqueViolation(entity, newVal, (Node)state);
|
||||
return super.setValue(entity,newVal,mappingPolicy);
|
||||
}
|
||||
|
||||
private void checkForUniqueViolation(Object entity,Object newVal, Node stateToBeSaved) {
|
||||
StoredEntityType set = template.getStoredEntityType(entity);
|
||||
if (newVal != null && property.isUnique()) {
|
||||
Object existingUniqueEntity = template.findUniqueEntity(set.getEntity().getType(),property.getNeo4jPropertyName(),newVal);
|
||||
if (existingUniqueEntity == null) return;
|
||||
final Node existingUniqueState = (Node)template.getPersistentState(existingUniqueEntity);
|
||||
if (existingUniqueState.equals(stateToBeSaved)) return;
|
||||
throw new DataIntegrityViolationException("Unique property "+property+" was to be set to duplicate value "+newVal);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyMissingSchemaIndexLabels(Object entity,Node state) {
|
||||
// TODO - This logic should rather be done once when the
|
||||
// entity is persisted for the first time rather than
|
||||
// on each update ....
|
||||
StoredEntityType set = template.getStoredEntityType(entity);
|
||||
if (set != null) {
|
||||
applyMissingSchemaIndexLabels(state, set);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyMissingSchemaIndexLabels(Node node, StoredEntityType set) {
|
||||
for (StoredEntityType ancestorSet : set.getSuperTypes()) {
|
||||
applyMissingSchemaIndexLabels(node, ancestorSet);
|
||||
}
|
||||
Label label = DynamicLabel.label( (String)set.getAlias());
|
||||
if (!node.hasLabel(label))
|
||||
node.addLabel(label);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,12 @@ import org.neo4j.graphdb.DynamicLabel;
|
||||
import org.neo4j.graphdb.Label;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.PropertyContainer;
|
||||
import org.neo4j.graphdb.index.Index;
|
||||
import org.neo4j.graphdb.schema.IndexDefinition;
|
||||
import org.neo4j.index.lucene.ValueContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
|
||||
import org.springframework.data.neo4j.support.Neo4jTemplate;
|
||||
import org.springframework.data.neo4j.support.mapping.StoredEntityType;
|
||||
@@ -76,16 +79,33 @@ public class SchemaIndexingPropertyFieldAccessorListenerFactory<S extends Proper
|
||||
|
||||
@Override
|
||||
public void valueChanged(Object entity, Object oldVal, Object newVal) {
|
||||
final PropertyContainer state = template.getPersistentState(entity);
|
||||
if (!(state instanceof Node)) {
|
||||
throw new IllegalArgumentException("not expecting to deal with non node property");
|
||||
}
|
||||
|
||||
applyMissingSchemaIndexLabels(entity,(Node)state);
|
||||
checkForUniqueViolation(entity, newVal, (Node)state);
|
||||
}
|
||||
|
||||
private void checkForUniqueViolation(Object entity,Object newVal, Node stateToBeSaved) {
|
||||
StoredEntityType set = template.getStoredEntityType(entity);
|
||||
if (newVal != null && property.isUnique()) {
|
||||
Object existingUniqueEntity = template.findUniqueEntity(set.getEntity().getType(),property.getNeo4jPropertyName(),newVal);
|
||||
if (existingUniqueEntity == null) return;
|
||||
final Node existingUniqueState = (Node)template.getPersistentState(existingUniqueEntity);
|
||||
if (existingUniqueState.equals(stateToBeSaved)) return;
|
||||
throw new DataIntegrityViolationException("Unique property "+property+" was to be set to duplicate value "+newVal);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyMissingSchemaIndexLabels(Object entity,Node state) {
|
||||
// TODO - This logic should rather be done once when the
|
||||
// entity is persisted for the first time rather than
|
||||
// on each update ....
|
||||
final PropertyContainer state = template.getPersistentState(entity);
|
||||
if (state instanceof Node) {
|
||||
Node node = (Node) state;
|
||||
StoredEntityType set = template.getStoredEntityType(entity);
|
||||
if (set != null) {
|
||||
applyMissingSchemaIndexLabels(node, set);
|
||||
}
|
||||
StoredEntityType set = template.getStoredEntityType(entity);
|
||||
if (set != null) {
|
||||
applyMissingSchemaIndexLabels(state, set);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,20 +18,29 @@ package org.springframework.data.neo4j.repository;
|
||||
|
||||
import org.neo4j.cypherdsl.grammar.Execute;
|
||||
import org.neo4j.cypherdsl.grammar.Skip;
|
||||
import org.neo4j.cypherdsl.querydsl.CypherQueryDSL;
|
||||
import org.neo4j.graphdb.PropertyContainer;
|
||||
import org.neo4j.graphdb.index.IndexHits;
|
||||
import org.neo4j.graphdb.index.ReadableIndex;
|
||||
import org.neo4j.helpers.collection.ClosableIterable;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.neo4j.helpers.collection.MapUtil;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.neo4j.annotation.Indexed;
|
||||
import org.springframework.data.neo4j.annotation.QueryType;
|
||||
import org.springframework.data.neo4j.conversion.EndResult;
|
||||
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity;
|
||||
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
|
||||
import org.springframework.data.neo4j.repository.query.CypherQuery;
|
||||
import org.springframework.data.neo4j.support.Neo4jTemplate;
|
||||
import org.springframework.data.neo4j.support.index.IndexType;
|
||||
import org.springframework.data.neo4j.support.query.QueryEngine;
|
||||
import org.springframework.data.repository.query.parser.Part;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
@@ -47,7 +56,8 @@ import static org.neo4j.helpers.collection.MapUtil.map;
|
||||
* @param <S> Type of backing state, either Node or Relationship
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public abstract class AbstractGraphRepository<S extends PropertyContainer, T> implements GraphRepository<T>, NamedIndexRepository<T>, SpatialRepository<T>, CypherDslRepository<T> {
|
||||
public abstract class AbstractGraphRepository<S extends PropertyContainer, T> implements
|
||||
GraphRepository<T>, NamedIndexRepository<T>, SpatialRepository<T>, CypherDslRepository<T> {
|
||||
private final LegacyIndexSearcher<S,T> legacyIndexSearcher;
|
||||
|
||||
/*
|
||||
@@ -237,6 +247,43 @@ public abstract class AbstractGraphRepository<S extends PropertyContainer, T> im
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Schema (aka Label based) Index based single finder which uses the default label
|
||||
* name for this type to find the entity.
|
||||
*
|
||||
* @param property
|
||||
* @param value
|
||||
* @return Single Entity with this property and value or null if it does not exist
|
||||
*/
|
||||
@Override
|
||||
public T findBySchemaPropertyValue(String property, Object value) {
|
||||
return findAllBySchemaPropertyValue(property,value).singleOrNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Schema (aka Label based) finder, uses the default label name for this type
|
||||
* to lookup entities.
|
||||
* @param property
|
||||
* @param value
|
||||
* @return Iterable over Entities with this property and value
|
||||
*/
|
||||
@Override
|
||||
public EndResult<T> findAllBySchemaPropertyValue(String property, Object value) {
|
||||
final String SCHEMA_PROP_MATCH_CLAUSE = "MATCH (entity:`%s`) where entity.`%s` = {propValue} return entity";
|
||||
|
||||
Neo4jPersistentEntity persistentEntity = template.getEntityType(clazz).getEntity();
|
||||
Neo4jPersistentProperty persistentProperty = (Neo4jPersistentProperty)persistentEntity.getPersistentProperty(property);
|
||||
if (persistentProperty.getIndexInfo() == null || !persistentProperty.getIndexInfo().isLabelBased() ) {
|
||||
throw new IllegalArgumentException(format("property {} is not schema indexed",property));
|
||||
}
|
||||
|
||||
Map<String,Object> params = new HashMap<String,Object>();
|
||||
params.put("propValue", value);
|
||||
String cypherQuery = format(SCHEMA_PROP_MATCH_CLAUSE,
|
||||
persistentProperty.getIndexInfo().getIndexName(), property );
|
||||
return template.query(cypherQuery,params).to(clazz);
|
||||
}
|
||||
|
||||
protected abstract S getById(long id);
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,5 +24,5 @@ import org.springframework.data.repository.NoRepositoryBean;
|
||||
* @since 12.01.11
|
||||
*/
|
||||
@NoRepositoryBean
|
||||
public interface GraphRepository<T> extends CRUDRepository<T>, IndexRepository<T>, TraversalRepository<T> {
|
||||
public interface GraphRepository<T> extends CRUDRepository<T>, IndexRepository<T>, SchemaIndexRepository<T>, TraversalRepository<T> {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j.repository;
|
||||
|
||||
import org.springframework.data.neo4j.conversion.EndResult;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* @author Nicki Watt
|
||||
* @since 01.03.2014
|
||||
*/
|
||||
public interface SchemaIndexRepository<T> {
|
||||
|
||||
@Transactional
|
||||
T findBySchemaPropertyValue(String property, Object value);
|
||||
|
||||
@Transactional
|
||||
EndResult<T> findAllBySchemaPropertyValue(String property, Object value);
|
||||
|
||||
}
|
||||
@@ -54,6 +54,7 @@ import org.springframework.data.neo4j.support.index.IndexProvider;
|
||||
import org.springframework.data.neo4j.support.index.IndexType;
|
||||
import org.springframework.data.neo4j.support.mapping.*;
|
||||
import org.springframework.data.neo4j.support.query.QueryEngine;
|
||||
import org.springframework.data.neo4j.support.schema.SchemaIndexProvider;
|
||||
import org.springframework.data.neo4j.template.GraphCallback;
|
||||
import org.springframework.data.neo4j.template.Neo4jOperations;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
@@ -67,6 +68,7 @@ import javax.validation.Validator;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static org.springframework.data.neo4j.support.ParameterCheck.notNull;
|
||||
|
||||
/**
|
||||
@@ -132,6 +134,7 @@ public class Neo4jTemplate implements Neo4jOperations, ApplicationContextAware {
|
||||
throw new IllegalArgumentException("Can't create graph repository for non-graph entity of type " + clazz);
|
||||
}
|
||||
|
||||
// Legacy Indexes Below
|
||||
|
||||
@Deprecated public <S extends PropertyContainer, T> Index<S> getIndex(Class<T> type) {
|
||||
notNull(type, "entity type");
|
||||
@@ -147,6 +150,31 @@ public class Neo4jTemplate implements Neo4jOperations, ApplicationContextAware {
|
||||
return getIndexProvider().getIndex(getPersistentEntity(type), indexName, indexType);
|
||||
}
|
||||
|
||||
// Schema Indexes Below
|
||||
|
||||
/**
|
||||
* Returns the unique entity of type entityClass (if it exists) otherwise returns null.
|
||||
* Note: this method will only work with the newer schema based indexes (not legacy)
|
||||
*
|
||||
* @param entityClass Entity class
|
||||
* @param propertyName Name of uniquely indexed property
|
||||
* @param value value of property to find
|
||||
* @param <T> the entity
|
||||
* @return the unique entity of type entityClass (if it exists) otherwise returns null.
|
||||
*
|
||||
*/
|
||||
public <T> T findUniqueEntity(final Class<T> entityClass,String propertyName, Object value) {
|
||||
final Neo4jPersistentEntityImpl<?> persistentEntity = getPersistentEntity(entityClass);
|
||||
Neo4jPersistentProperty persistentProperty = persistentEntity.getPersistentProperty(propertyName);
|
||||
|
||||
boolean labelIndexed = persistentProperty.isIndexed() && persistentProperty.getIndexInfo().isLabelBased();
|
||||
boolean indexedButNotUnique = persistentProperty.isIndexed() && !persistentProperty.isUnique();
|
||||
if (!labelIndexed || indexedButNotUnique) {
|
||||
throw new IllegalArgumentException(format("propertyName '%s' must be uniquely (schema) indexed however it is not", propertyName));
|
||||
}
|
||||
return (T)getSchemaIndexProvider().findAll(persistentProperty,value).singleOrNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if a transaction manager is available and a transaction is currently running
|
||||
*/
|
||||
@@ -600,6 +628,10 @@ public class Neo4jTemplate implements Neo4jOperations, ApplicationContextAware {
|
||||
return infrastructure.getIndexProvider();
|
||||
}
|
||||
|
||||
private SchemaIndexProvider getSchemaIndexProvider() {
|
||||
return infrastructure.getSchemaIndexProvider();
|
||||
}
|
||||
|
||||
private Neo4jPersistentEntityImpl<?> getPersistentEntity(Class<?> type) {
|
||||
return getMappingContext().getPersistentEntity(type);
|
||||
}
|
||||
|
||||
@@ -15,24 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.neo4j.invalid.unique;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.neo4j.unique.domain.Club;
|
||||
import org.springframework.data.neo4j.unique.domain.UniqueClub;
|
||||
import org.springframework.data.neo4j.unique.domain.UniqueNumericIdClub;
|
||||
import org.springframework.data.neo4j.unique.repository.ClubRepository;
|
||||
import org.springframework.data.neo4j.unique.repository.UniqueClubRepository;
|
||||
import org.springframework.data.neo4j.unique.repository.UniqueNumericIdClubRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
|
||||
@@ -282,7 +282,6 @@ public class GraphRepositoryTests {
|
||||
}
|
||||
|
||||
@Test @Transactional
|
||||
// @Ignore("cypher bug with escaped params")
|
||||
public void testFindWithMultipleParameters() {
|
||||
final int limit = 2;
|
||||
Iterable<Person> teamMembers = personRepository.findSomeTeamMembers(testTeam.sdg.getName(), 0, limit);
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.neo4j.unique.domain.Club;
|
||||
import org.springframework.data.neo4j.invalid.unique.InvalidClub;
|
||||
import org.springframework.data.neo4j.unique.domain.UniqueClub;
|
||||
import org.springframework.data.neo4j.unique.domain.UniqueNumericIdClub;
|
||||
import org.springframework.data.neo4j.unique.repository.ClubRepository;
|
||||
import org.springframework.data.neo4j.invalid.unique.InvalidClubRepository;
|
||||
import org.springframework.data.neo4j.unique.repository.UniqueClubRepository;
|
||||
import org.springframework.data.neo4j.unique.repository.UniqueNumericIdClubRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = {"classpath:unique-test-context.xml"})
|
||||
@Transactional
|
||||
public class UniqueEntityTests {
|
||||
|
||||
@Autowired
|
||||
private ClubRepository clubRepository;
|
||||
|
||||
@Autowired
|
||||
private UniqueClubRepository uniqueClubRepository;
|
||||
|
||||
@Autowired
|
||||
protected GraphDatabaseService graphDatabaseService;
|
||||
|
||||
@Autowired
|
||||
private UniqueNumericIdClubRepository uniqueNumericIdClubRepository;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
clubRepository.deleteAll();
|
||||
uniqueClubRepository.deleteAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldOnlyCreateSingleInstanceForUniqueNodeEntity() {
|
||||
UniqueClub club = new UniqueClub();
|
||||
club.setName("foo");
|
||||
uniqueClubRepository.save(club);
|
||||
|
||||
club = new UniqueClub();
|
||||
club.setName("foo");
|
||||
uniqueClubRepository.save(club);
|
||||
|
||||
assertEquals(1, uniqueClubRepository.count());
|
||||
}
|
||||
|
||||
@Test(expected = MappingException.class)
|
||||
public void shouldFailOnNullPropertyValue() {
|
||||
UniqueClub club = new UniqueClub();
|
||||
club.setName(null);
|
||||
uniqueClubRepository.save(club);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldOnlyCreateSingleInstanceForUniqueNumericNodeEntity() {
|
||||
UniqueNumericIdClub club = new UniqueNumericIdClub();
|
||||
club.setClubId(100L);
|
||||
uniqueNumericIdClubRepository.save(club);
|
||||
|
||||
club = new UniqueNumericIdClub(100L);
|
||||
uniqueNumericIdClubRepository.save(club);
|
||||
|
||||
assertEquals(1, uniqueNumericIdClubRepository.count());
|
||||
}
|
||||
|
||||
@Test(expected = MappingException.class)
|
||||
public void shouldFailOnNullNumericPropertyValue() {
|
||||
UniqueNumericIdClub club = new UniqueNumericIdClub();
|
||||
club.setClubId(null);
|
||||
uniqueNumericIdClubRepository.save(club);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCreateMultipleInstancesForNonUniqueNodeEntity() {
|
||||
Club club = new Club();
|
||||
club.setName("foo");
|
||||
clubRepository.save(club);
|
||||
|
||||
club = new Club();
|
||||
club.setName("foo");
|
||||
clubRepository.save(club);
|
||||
|
||||
assertEquals(2, clubRepository.count());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deletingUniqueNodeShouldRemoveItFromTheUniqueIndex() {
|
||||
UniqueClub club = new UniqueClub();
|
||||
club.setName("foo");
|
||||
uniqueClubRepository.save(club);
|
||||
assertEquals(1, uniqueClubRepository.count());
|
||||
|
||||
uniqueClubRepository.delete(club);
|
||||
assertEquals(0, uniqueClubRepository.count());
|
||||
}
|
||||
|
||||
@Test(expected = DataIntegrityViolationException.class)
|
||||
public void updatingToADuplicateValueShouldCauseAnException() {
|
||||
uniqueClubRepository.save(new UniqueClub("foo"));
|
||||
UniqueClub club2 = uniqueClubRepository.save(new UniqueClub("bar"));
|
||||
assertEquals(2, uniqueClubRepository.count());
|
||||
club2.setName("foo");
|
||||
uniqueClubRepository.save(club2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatingToANewValueShouldKeepTheEntityUnique() {
|
||||
UniqueClub club = uniqueClubRepository.save(new UniqueClub("foo"));
|
||||
assertEquals(1, uniqueClubRepository.count());
|
||||
club.setName("bar");
|
||||
uniqueClubRepository.save(club);
|
||||
assertEquals(1, uniqueClubRepository.count());
|
||||
final UniqueClub club2 = uniqueClubRepository.save(new UniqueClub("bar"));
|
||||
assertEquals(club.getId(),club2.getId());
|
||||
}
|
||||
@Test
|
||||
public void updatingToANewValueShouldAlsoUpdateTheIndex() {
|
||||
UniqueClub club = uniqueClubRepository.save(new UniqueClub("foo"));
|
||||
assertEquals(1, uniqueClubRepository.count());
|
||||
assertEquals(club.getId(),uniqueClubRepository.findByPropertyValue("name","foo").getId());
|
||||
club.setName("bar");
|
||||
uniqueClubRepository.save(club);
|
||||
assertEquals(club.getId(),uniqueClubRepository.findByPropertyValue("name","bar").getId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.common;
|
||||
|
||||
public interface CommonClub {
|
||||
|
||||
public Long getId();
|
||||
|
||||
public String getName();
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.common;
|
||||
|
||||
public interface CommonUniqueClub {
|
||||
|
||||
public Long getId();
|
||||
|
||||
public String getName();
|
||||
|
||||
public void setName(String name);
|
||||
|
||||
public String getDescription();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/**
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.common;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.neo4j.graphdb.Transaction;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.unique.schemabased.domain.Club;
|
||||
import org.springframework.data.neo4j.unique.schemabased.domain.UniqueClub;
|
||||
import org.springframework.data.neo4j.unique.schemabased.domain.UniqueNumericIdClub;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public abstract class CommonUniqueEntityTestBase {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
clearDownAllRepositories();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldOnlyCreateSingleInstanceForUniqueNodeEntity() {
|
||||
CommonUniqueClub club1 = createUniqueClub("foo", null);
|
||||
CommonUniqueClub club2 = createUniqueClub("foo", null);
|
||||
CommonUniqueClub club3 = createUniqueClub("foo", null);
|
||||
|
||||
assertEquals(1, getUniqueClubRepository().count());
|
||||
assertEquals("Expected same node Ids", club1.getId(),club2.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldMergeNewUniqueNodeEntityDataWithExistingDataWhenSaving() {
|
||||
CommonUniqueClub club1 = createUniqueClub("bar", "description-1");
|
||||
CommonUniqueClub club2 = createUniqueClub("bar", "description-2");
|
||||
assertEquals(1, getUniqueClubRepository().count());
|
||||
assertEquals("Expected same node Ids", club1.getId(),club2.getId());
|
||||
CommonUniqueClub retrievedClub = (CommonUniqueClub)getUniqueClubRepository().findOne(club1.getId());
|
||||
assertEquals("Description not merged as expected",
|
||||
"description-2", retrievedClub.getDescription());
|
||||
}
|
||||
|
||||
@Test(expected = MappingException.class)
|
||||
public void shouldFailOnNullPropertyValue() {
|
||||
createUniqueClub(null, null);
|
||||
}
|
||||
|
||||
@Test(expected = MappingException.class)
|
||||
public void shouldFailOnNullNumericPropertyValue() {
|
||||
createUniqueNumericClub(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldOnlyCreateSingleInstanceForUniqueNumericNodeEntity() {
|
||||
CommonUniqueNumericIdClub club1 = createUniqueNumericClub(100L);
|
||||
CommonUniqueNumericIdClub club2 = createUniqueNumericClub(100L);
|
||||
assertEquals(1, getUniqueNumericIdClubRepository().count());
|
||||
assertEquals("Expected same node Ids", club1.getId(),club2.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCreateMultipleInstancesForNonUniqueNodeEntity() {
|
||||
CommonClub club1 = createNonUniqueClub("foo");
|
||||
CommonClub club2 = createNonUniqueClub("foo");
|
||||
assertEquals(2, getClubRepository().count());
|
||||
assertNotEquals("Expected different node Ids", club1.getId(), club2.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deletingUniqueNodeShouldRemoveItFromTheUniqueIndex() {
|
||||
CommonUniqueClub club1 = createUniqueClub("foo", null);
|
||||
assertEquals("Expected one unique entity",1, getUniqueClubRepository().count());
|
||||
getUniqueClubRepository().delete(club1);
|
||||
assertEquals("Expected zero unique entities",0, getUniqueClubRepository().count());
|
||||
}
|
||||
|
||||
@Test(expected = DataIntegrityViolationException.class)
|
||||
public void updatingToADuplicateValueShouldCauseAnException() {
|
||||
CommonUniqueClub club1 = createUniqueClub("foo", "foo description");
|
||||
CommonUniqueClub club2 = createUniqueClub("bar", "bar description");
|
||||
assertEquals(2, getUniqueClubRepository().count());
|
||||
assertNotEquals("Expected different node Ids", club1.getId(), club2.getId());
|
||||
club2.setName("foo");
|
||||
getUniqueClubRepository().save(club2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatingToANewValueShouldAlsoUpdateTheIndex() {
|
||||
CommonUniqueClub club1 = createUniqueClub("foo", "foo description");
|
||||
assertEquals(1, getUniqueClubRepository().count());
|
||||
CommonUniqueClub fooClub = lookupEntityByUniquePropertyValue("name", "foo");
|
||||
assertNotNull(fooClub);
|
||||
assertEquals(club1.getId(),fooClub.getId());
|
||||
|
||||
club1.setName("bar");
|
||||
getUniqueClubRepository().save(club1);
|
||||
assertEquals(1, getUniqueClubRepository().count());
|
||||
CommonUniqueClub currentClub = lookupEntityByUniquePropertyValue("name", "bar");
|
||||
assertNotNull(currentClub);
|
||||
assertEquals(club1.getId(),currentClub.getId());
|
||||
|
||||
// We should not find "foo" now
|
||||
CommonUniqueClub redundantClub = lookupEntityByUniquePropertyValue("name", "foo");
|
||||
assertNull(redundantClub);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatingToANewValueShouldKeepTheEntityUnique() {
|
||||
|
||||
CommonUniqueClub club1 = createUniqueClub("foo", "foo description");
|
||||
assertEquals(1, getUniqueClubRepository().count());
|
||||
CommonUniqueClub fooClub = lookupEntityByUniquePropertyValue("name", "foo");
|
||||
assertNotNull(fooClub);
|
||||
assertEquals(club1.getId(),fooClub.getId());
|
||||
|
||||
club1.setName("bar");
|
||||
getUniqueClubRepository().save(club1);
|
||||
assertEquals(1, getUniqueClubRepository().count());
|
||||
CommonUniqueClub currentClub = lookupEntityByUniquePropertyValue("name", "bar");
|
||||
assertNotNull(currentClub);
|
||||
assertEquals(club1.getId(),currentClub.getId());
|
||||
|
||||
// We should not find "foo" now
|
||||
CommonUniqueClub redundantClub = lookupEntityByUniquePropertyValue("name", "foo");
|
||||
assertNull(redundantClub);
|
||||
}
|
||||
|
||||
@Ignore("This scenario does not work, could be transactional issues")
|
||||
@Test
|
||||
public void updatingToANewValueShouldKeepTheEntityUniqueAndOldValueShouldBeReusableThereafter() {
|
||||
|
||||
updatingToANewValueShouldAlsoUpdateTheIndex();
|
||||
|
||||
// At this stage we should find "bar" but not "foo"
|
||||
CommonUniqueClub currentClub = (CommonUniqueClub)getUniqueClubRepository().findBySchemaPropertyValue("name", "bar");
|
||||
assertNotNull(currentClub);
|
||||
CommonUniqueClub redundantClub = (CommonUniqueClub)getUniqueClubRepository().findBySchemaPropertyValue("name", "foo");
|
||||
assertNull(redundantClub);
|
||||
|
||||
CommonUniqueClub fooReusingClub = createUniqueClub("foo", "foo description");
|
||||
assertNotEquals("A new id should have been created for re-use of foo but it was not!",currentClub.getId(),fooReusingClub.getId());
|
||||
assertEquals(2, getUniqueClubRepository().count());
|
||||
|
||||
}
|
||||
|
||||
protected abstract CommonUniqueClub lookupEntityByUniquePropertyValue(String propertyName, Object value);
|
||||
|
||||
protected abstract void clearDownAllRepositories();
|
||||
|
||||
protected abstract CommonUniqueClub createUniqueClub(String name, String description);
|
||||
|
||||
protected abstract CommonUniqueNumericIdClub createUniqueNumericClub(Long clubId);
|
||||
|
||||
protected abstract CommonClub createNonUniqueClub(String name);
|
||||
|
||||
protected abstract GraphRepository getUniqueNumericIdClubRepository();
|
||||
|
||||
protected abstract GraphRepository getUniqueClubRepository();
|
||||
|
||||
protected abstract GraphRepository getClubRepository();
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.common;
|
||||
|
||||
public interface CommonUniqueNumericIdClub {
|
||||
|
||||
public Long getId();
|
||||
|
||||
public Long getClubId();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.legacy;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.unique.common.CommonClub;
|
||||
import org.springframework.data.neo4j.unique.common.CommonUniqueClub;
|
||||
import org.springframework.data.neo4j.unique.common.CommonUniqueEntityTestBase;
|
||||
import org.springframework.data.neo4j.unique.common.CommonUniqueNumericIdClub;
|
||||
import org.springframework.data.neo4j.unique.legacy.domain.Club;
|
||||
import org.springframework.data.neo4j.unique.legacy.domain.UniqueClub;
|
||||
import org.springframework.data.neo4j.unique.legacy.domain.UniqueNumericIdClub;
|
||||
import org.springframework.data.neo4j.unique.legacy.repository.ClubRepository;
|
||||
import org.springframework.data.neo4j.unique.legacy.repository.UniqueClubRepository;
|
||||
import org.springframework.data.neo4j.unique.legacy.repository.UniqueNumericIdClubRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = {"classpath:unique-legacy-test-context.xml"})
|
||||
@Transactional
|
||||
public class UniqueLegacyIndexBasedEntityTests extends CommonUniqueEntityTestBase {
|
||||
|
||||
@Autowired
|
||||
private ClubRepository clubRepository;
|
||||
|
||||
@Autowired
|
||||
private UniqueClubRepository uniqueClubRepository;
|
||||
|
||||
@Autowired
|
||||
protected GraphDatabaseService graphDatabaseService;
|
||||
|
||||
@Autowired
|
||||
private UniqueNumericIdClubRepository uniqueNumericIdClubRepository;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
super.setup();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearDownAllRepositories() {
|
||||
uniqueClubRepository.deleteAll();
|
||||
clubRepository.deleteAll();
|
||||
uniqueClubRepository.deleteAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test(expected = DataIntegrityViolationException.class)
|
||||
@Ignore("This method now throws a DataIntegrityViolationException for legacy indexes" +
|
||||
" - verify if this is correct")
|
||||
public void shouldOnlyCreateSingleInstanceForUniqueNumericNodeEntity() {
|
||||
CommonUniqueNumericIdClub club1 = createUniqueNumericClub(100L);
|
||||
CommonUniqueNumericIdClub club2 = createUniqueNumericClub(100L);
|
||||
assertEquals(1, getUniqueNumericIdClubRepository().count());
|
||||
assertEquals("Expected same node Ids", club1.getId(),club2.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommonClub createNonUniqueClub(String name) {
|
||||
Club club = new Club();
|
||||
club.setName(name);
|
||||
clubRepository.save(club);
|
||||
return club;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommonUniqueClub createUniqueClub(String name, String description) {
|
||||
UniqueClub club = new UniqueClub();
|
||||
club.setName(name);
|
||||
club.setDescription(description);
|
||||
uniqueClubRepository.save(club);
|
||||
return club; }
|
||||
|
||||
@Override
|
||||
protected CommonUniqueNumericIdClub createUniqueNumericClub(Long clubId) {
|
||||
UniqueNumericIdClub club = new UniqueNumericIdClub();
|
||||
club.setClubId(clubId);
|
||||
uniqueNumericIdClubRepository.save(club);
|
||||
return club;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommonUniqueClub lookupEntityByUniquePropertyValue(String propertyName, Object value) {
|
||||
return (CommonUniqueClub)getUniqueClubRepository().findByPropertyValue(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GraphRepository getUniqueNumericIdClubRepository() {
|
||||
return uniqueNumericIdClubRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GraphRepository getUniqueClubRepository() {
|
||||
return uniqueClubRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GraphRepository getClubRepository() {
|
||||
return clubRepository;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique;
|
||||
package org.springframework.data.neo4j.unique.legacy;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.neo4j.graphdb.*;
|
||||
@@ -13,13 +13,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.domain;
|
||||
package org.springframework.data.neo4j.unique.legacy.domain;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.GraphId;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
import org.springframework.data.neo4j.unique.common.CommonClub;
|
||||
|
||||
@NodeEntity
|
||||
public class Club {
|
||||
public class Club implements CommonClub {
|
||||
|
||||
private String name;
|
||||
|
||||
@@ -33,4 +34,8 @@ public class Club {
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.legacy.domain;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.GraphId;
|
||||
import org.springframework.data.neo4j.annotation.Indexed;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
import org.springframework.data.neo4j.support.index.IndexType;
|
||||
import org.springframework.data.neo4j.unique.common.CommonUniqueClub;
|
||||
|
||||
@NodeEntity
|
||||
public class UniqueClub implements CommonUniqueClub {
|
||||
|
||||
@Indexed(unique = true,indexType = IndexType.SIMPLE)
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
|
||||
@GraphId
|
||||
Long id;
|
||||
|
||||
public UniqueClub() {
|
||||
}
|
||||
|
||||
public UniqueClub(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public UniqueClub(String name, String description) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
@@ -13,16 +13,18 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.domain;
|
||||
package org.springframework.data.neo4j.unique.legacy.domain;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.GraphId;
|
||||
import org.springframework.data.neo4j.annotation.Indexed;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
import org.springframework.data.neo4j.support.index.IndexType;
|
||||
import org.springframework.data.neo4j.unique.common.CommonUniqueNumericIdClub;
|
||||
|
||||
@NodeEntity
|
||||
public class UniqueNumericIdClub {
|
||||
public class UniqueNumericIdClub implements CommonUniqueNumericIdClub {
|
||||
|
||||
@Indexed(unique = true)
|
||||
@Indexed(unique = true, indexType = IndexType.SIMPLE)
|
||||
private Long clubId;
|
||||
|
||||
@GraphId
|
||||
@@ -13,11 +13,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.repository;
|
||||
package org.springframework.data.neo4j.unique.legacy.repository;
|
||||
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.repository.NamedIndexRepository;
|
||||
import org.springframework.data.neo4j.unique.domain.Club;
|
||||
import org.springframework.data.neo4j.unique.legacy.domain.Club;
|
||||
|
||||
public interface ClubRepository extends GraphRepository<Club>, NamedIndexRepository<Club> {
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.repository;
|
||||
package org.springframework.data.neo4j.unique.legacy.repository;
|
||||
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.repository.NamedIndexRepository;
|
||||
import org.springframework.data.neo4j.unique.domain.Club;
|
||||
import org.springframework.data.neo4j.unique.domain.UniqueClub;
|
||||
import org.springframework.data.neo4j.unique.legacy.domain.Club;
|
||||
import org.springframework.data.neo4j.unique.legacy.domain.UniqueClub;
|
||||
|
||||
public interface UniqueClubRepository extends GraphRepository<UniqueClub>, NamedIndexRepository<Club> {
|
||||
|
||||
@@ -13,13 +13,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.repository;
|
||||
package org.springframework.data.neo4j.unique.legacy.repository;
|
||||
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.repository.NamedIndexRepository;
|
||||
import org.springframework.data.neo4j.unique.domain.Club;
|
||||
import org.springframework.data.neo4j.unique.domain.UniqueClub;
|
||||
import org.springframework.data.neo4j.unique.domain.UniqueNumericIdClub;
|
||||
import org.springframework.data.neo4j.unique.legacy.domain.UniqueNumericIdClub;
|
||||
|
||||
public interface UniqueNumericIdClubRepository extends GraphRepository<UniqueNumericIdClub>, NamedIndexRepository<UniqueNumericIdClub> {
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.schemabased;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.unique.common.CommonClub;
|
||||
import org.springframework.data.neo4j.unique.common.CommonUniqueClub;
|
||||
import org.springframework.data.neo4j.unique.common.CommonUniqueEntityTestBase;
|
||||
import org.springframework.data.neo4j.unique.common.CommonUniqueNumericIdClub;
|
||||
import org.springframework.data.neo4j.unique.schemabased.domain.Club;
|
||||
import org.springframework.data.neo4j.unique.schemabased.domain.UniqueClub;
|
||||
import org.springframework.data.neo4j.unique.schemabased.domain.UniqueNumericIdClub;
|
||||
import org.springframework.data.neo4j.unique.schemabased.repository.ClubRepository;
|
||||
import org.springframework.data.neo4j.unique.schemabased.repository.UniqueClubRepository;
|
||||
import org.springframework.data.neo4j.unique.schemabased.repository.UniqueNumericIdClubRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = {"classpath:unique-schema-test-context.xml"})
|
||||
@Transactional
|
||||
public class UniqueSchemaBasedEntityTests extends CommonUniqueEntityTestBase {
|
||||
|
||||
@Autowired
|
||||
private ClubRepository clubRepository;
|
||||
|
||||
@Autowired
|
||||
private UniqueClubRepository uniqueClubRepository;
|
||||
|
||||
@Autowired
|
||||
private UniqueNumericIdClubRepository uniqueNumericIdClubRepository;
|
||||
|
||||
@Autowired
|
||||
protected GraphDatabaseService graphDatabaseService;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
super.setup();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearDownAllRepositories() {
|
||||
uniqueClubRepository.deleteAll();
|
||||
clubRepository.deleteAll();
|
||||
uniqueNumericIdClubRepository.deleteAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Ignore("This scenario does not currently work")
|
||||
@Test
|
||||
public void updatingToANewValueShouldKeepTheEntityUniqueAndOldValueShouldBeReusableThereafter() {
|
||||
super.updatingToANewValueShouldKeepTheEntityUniqueAndOldValueShouldBeReusableThereafter();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommonUniqueClub lookupEntityByUniquePropertyValue(String propertyName, Object value) {
|
||||
return (CommonUniqueClub)getUniqueClubRepository().findBySchemaPropertyValue(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommonClub createNonUniqueClub(String name) {
|
||||
Club club = new Club();
|
||||
club.setName(name);
|
||||
clubRepository.save(club);
|
||||
return club;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommonUniqueClub createUniqueClub(String name, String description) {
|
||||
UniqueClub club = new UniqueClub();
|
||||
club.setName(name);
|
||||
club.setDescription(description);
|
||||
uniqueClubRepository.save(club);
|
||||
return club; }
|
||||
|
||||
@Override
|
||||
protected CommonUniqueNumericIdClub createUniqueNumericClub(Long clubId) {
|
||||
UniqueNumericIdClub club = new UniqueNumericIdClub();
|
||||
club.setClubId(clubId);
|
||||
uniqueNumericIdClubRepository.save(club);
|
||||
return club;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GraphRepository getUniqueNumericIdClubRepository() {
|
||||
return uniqueNumericIdClubRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GraphRepository getUniqueClubRepository() {
|
||||
return uniqueClubRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GraphRepository getClubRepository() {
|
||||
return clubRepository;
|
||||
}
|
||||
}
|
||||
@@ -13,29 +13,20 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.domain;
|
||||
package org.springframework.data.neo4j.unique.schemabased.domain;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.GraphId;
|
||||
import org.springframework.data.neo4j.annotation.Indexed;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
import org.springframework.data.neo4j.support.index.IndexType;
|
||||
import org.springframework.data.neo4j.unique.common.CommonClub;
|
||||
|
||||
@NodeEntity
|
||||
public class UniqueClub {
|
||||
public class Club implements CommonClub {
|
||||
|
||||
@Indexed(unique = true,indexType = IndexType.SIMPLE)
|
||||
private String name;
|
||||
|
||||
@GraphId
|
||||
Long id;
|
||||
|
||||
public UniqueClub() {
|
||||
}
|
||||
|
||||
public UniqueClub(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -47,4 +38,4 @@ public class UniqueClub {
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.schemabased.domain;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.GraphId;
|
||||
import org.springframework.data.neo4j.annotation.Indexed;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
import org.springframework.data.neo4j.support.index.IndexType;
|
||||
import org.springframework.data.neo4j.unique.common.CommonUniqueClub;
|
||||
|
||||
@NodeEntity
|
||||
public class UniqueClub implements CommonUniqueClub {
|
||||
|
||||
@Indexed(unique = true,indexType = IndexType.LABEL)
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
|
||||
@GraphId
|
||||
Long id;
|
||||
|
||||
public UniqueClub() {
|
||||
}
|
||||
|
||||
public UniqueClub(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.schemabased.domain;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.GraphId;
|
||||
import org.springframework.data.neo4j.annotation.Indexed;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
import org.springframework.data.neo4j.support.index.IndexType;
|
||||
import org.springframework.data.neo4j.unique.common.CommonUniqueNumericIdClub;
|
||||
|
||||
@NodeEntity
|
||||
public class UniqueNumericIdClub implements CommonUniqueNumericIdClub {
|
||||
|
||||
@Indexed(unique = true, indexType = IndexType.LABEL)
|
||||
private Long clubId;
|
||||
|
||||
@GraphId
|
||||
Long id;
|
||||
|
||||
public UniqueNumericIdClub() {
|
||||
}
|
||||
|
||||
public UniqueNumericIdClub(Long clubId) {
|
||||
this.clubId = clubId;
|
||||
}
|
||||
|
||||
public Long getClubId() {
|
||||
return clubId;
|
||||
}
|
||||
|
||||
public void setClubId(Long clubId) {
|
||||
this.clubId = clubId;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.schemabased.repository;
|
||||
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.unique.schemabased.domain.Club;
|
||||
|
||||
public interface ClubRepository extends GraphRepository<Club> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.schemabased.repository;
|
||||
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.unique.schemabased.domain.UniqueClub;
|
||||
|
||||
public interface UniqueClubRepository extends GraphRepository<UniqueClub> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.unique.schemabased.repository;
|
||||
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.unique.schemabased.domain.UniqueNumericIdClub;
|
||||
|
||||
public interface UniqueNumericIdClubRepository extends GraphRepository<UniqueNumericIdClub> {
|
||||
|
||||
}
|
||||
@@ -13,12 +13,12 @@
|
||||
<context:annotation-config/>
|
||||
|
||||
<bean class="org.springframework.data.neo4j.config.Neo4jConfiguration">
|
||||
<property name="basePackage" value="org.springframework.data.neo4j.unique"/>
|
||||
<property name="basePackage" value="org.springframework.data.neo4j.unique.legacy.domain"/>
|
||||
</bean>
|
||||
|
||||
<bean id="graphDatabaseService" class="org.neo4j.test.ImpermanentGraphDatabase" destroy-method="shutdown"/>
|
||||
|
||||
<neo4j:repositories base-package="org.springframework.data.neo4j.unique.repository"/>
|
||||
<neo4j:repositories base-package="org.springframework.data.neo4j.unique.legacy.repository"/>
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
|
||||
http://www.springframework.org/schema/data/neo4j http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
|
||||
|
||||
<context:spring-configured/>
|
||||
<context:annotation-config/>
|
||||
|
||||
<bean class="org.springframework.data.neo4j.config.Neo4jConfiguration">
|
||||
<property name="basePackage" value="org.springframework.data.neo4j.unique.schemabased.domain"/>
|
||||
</bean>
|
||||
|
||||
<bean id="graphDatabaseService" class="org.neo4j.test.ImpermanentGraphDatabase" destroy-method="shutdown"/>
|
||||
|
||||
<neo4j:repositories base-package="org.springframework.data.neo4j.unique.schemabased.repository"/>
|
||||
|
||||
</beans>
|
||||
|
||||
Reference in New Issue
Block a user