当我使用Spring Data Neo4j(SDN)查找节点实体时,我遇到了一些奇怪的行为。如果我使用GraphRepository.findOne(long),它将返回具有该标识符的实体,即使该实体的类型不同。
这是我(非常)简化的实体结构:
@NodeEntity
protected abstract class BaseEntity {
@GraphId
private Long id;
@JsonIgnore
@RelatedTo(type = RelationType.ENTITY_AUDIT)
private Audit audit;
}
@NodeEntity
public final class Person extends BaseEntity {
@Indexed(indexType = IndexType.FULLTEXT)
private String firstName;
@Indexed(indexType = IndexType.FULLTEXT)
private String lastName;
}
@NodeEntity
public class Audit extends BaseEntity {
@RelatedTo(type = RelationType.ENTITY_AUDIT, direction = Direction.INCOMING)
private BaseEntity parent;
private Long date;
private String user;
}
对于每种实体类型,我都创建了这样的存储库:
@Repository
public interface PersonRepository extends GraphRepository<Person> {}
@Repository
public interface AuditRepository extends GraphRepository<Audit> {}
我的服务层类有一个抽象基类。这就是他们大致的样子:
public abstract class MyServiceImpl<T extends BaseEntity> implements MyService<T> {
private GraphRepository<T> repository;
public MyServiceImpl(final GraphRepository<T> repository) {
this.repository = repository;
}
@Override
public T read(final Long identifier) throws EntityNotFoundException {
return repository.findOne(identifier);
}
@Override
public T create(final T entity) {
return repository.save(entity);
}
}
@Service
public class PersonServiceImpl extends MyServiceImpl<Person> implements PersonService {
private PersonRepository personRepository;
@Autowired
public PersonServiceImpl(final PersonRepository personRepository) {
super(personRepository);
this.personRepository = personRepository;
}
}
当我执行以下代码时,结果不符合预期:
Person person = new Person();
person.setFirstName("Test");
person.setLastName("Person");
personService.create(person);
// suppose the person identifier is 1L
final Audit audit = auditRepository.findOne(1L);
您希望AuditRepository将返回null,但事实并非如此。相反,它返回一个标识为1L的Audit,并在其所有属性中返回null。似乎只要有一个节点对应于给定的标识符,它就会返回,不管它的类型是什么。如果Person和Audit有匹配的属性名称,那么它们也会包含它们的值...是所有这些预期的行为,还是我错过了什么?
目前,我已经使用下面的代码解决了这个问题,我自己进行了类型检查。
public abstract class MyServiceImpl<T extends BaseEntity> implements MyService<T> {
private GraphRepository<T> repository;
public MyServiceImpl(final GraphRepository<T> repository) {
this.repository = repository;
}
@Override
public T read(final Long identifier) throws EntityNotFoundException {
return get(identifier);
}
protected T get(final Long identifier) throws EntityNotFoundException {
final T entity = repository.findOne(identifier);
final Class<T> type = getServiceType();
if (entity == null || !(type.equals(repository.getStoredJavaType(entity)))) {
throw new EntityNotFoundException(type, identifier);
}
return entity;
}
@SuppressWarnings("unchecked")
private Class<T> getServiceType() {
return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}
}
如果您需要更多配置,请告知我们。
我的框架版本是:
<spring.version>3.2.0.RC1</spring.version>
<neo4j.version>1.8</neo4j.version>
<spring.data.neo4j.version>2.1.0.RELEASE</spring.data.neo4j.version>
答案 0 :(得分:2)
我们之前有这种行为,它在返回错误的实体类型时失败,我们更改了这种行为,以便您提供的类型用于自动将节点投影到。
public <S extends PropertyContainer, T> T createEntityFromStoredType(S state, MappingPolicy mappingPolicy) {..}
模板。 createEntityFromStoredType(node,null)将为您提供存储状态的对象。
public Class getStoredJavaType(Object entity) {}
为您提供节点或关系(或实体)的存储类
我们讨论了改变行为和失败的esp。在存储库中。
问题是,那会发生什么?一个例外?一个空的结果? ...
一般来说,如果你提供一个有效的原始node-id,那么返回错误或Null似乎也不是正确的答案?