5

当我使用 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 且所有属性都为 null 的 Audit。似乎只要有一个与给定标识符对应的节点,它就会被返回,不管它的类型是什么。如果 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>
4

1 回答 1

2

在返回错误的实体类型之前,我们有该行为,我们更改了该行为,以便您提供的类型用于自动将节点投影到。

public <S extends PropertyContainer, T> T createEntityFromStoredType(S state, MappingPolicy mappingPolicy) {..}

模板。createEntityFromStoredType(node, null) 将为您提供具有存储状态的对象。

public Class getStoredJavaType(Object entity) {} 

为您提供节点或关系(或实体)的存储类

我们讨论了改变行为和失败的问题。在存储库中。

问题是,那会发生什么?例外?空结果?...

通常,如果您提供有效的原始节点 ID,返回错误或 Null 似乎也不是正确答案?

于 2012-11-14T08:40:37.637 回答