当前位置: 首页 > 知识库问答 >
问题:

使用Spring数据Neo4j解析实体会返回错误的实体类型

徐鸿文
2023-03-14

当我使用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且在其所有属性中为空的审计。似乎只要有一个节点对应于给定的标识符,它就会被返回,而不管它的类型是什么。如果人员和审计有匹配的属性名称,它们也会包含它们的值...所有这些都是预期的行为,还是我错过了什么?

目前,我已经通过下面的代码解决了这个问题,我自己在其中进行类型检查。

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>

共有1个答案

吉俊德
2023-03-14

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

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

样板createEntityFromStoredType(节点,null)将获取具有存储状态的对象。

public Class getStoredJavaType(Object entity) {} 

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

我们讨论了如何改变行为,尤其是在存储库中失败。

问题是,接下来会发生什么?例外情况?空结果。。。

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

 类似资料:
  • 图像我有以下实体:公司和员工,带有Spring数据neo4j注释: Company.java 受雇者JAVA 然后是这些实体的关系实体: 那么如何保留和中的引用呢? Company.java 或 人JAVA 或

  • 在本地开发环境中使用Eclipse(Mars.1发行版(4.5.1))中的Forge 1.8.9。 在环游世界一小段时间后,然后注销该世界并返回(同一个会话中,退出并关闭MC),世界将无法出现在控制台中。该位置与“一切正常”登录中的位置相同。另外还有一个错误的位置!错误 控制台的错误如下: 我已经尝试过一些变化,包括Minecraft Forge:使用正确的连接游戏侦听器进行设置位置和角度,但不使

  • 如何返回与JPA中的父级有关系的实体列表? 我有一个用户实体,在名为的属性上有@OneToMany映射。子实体为Pet类型。这只是一种单向关系。 如何在JPA中编写返回给定用户的所有宠物的连接?

  • 对于任何一个 ORM 工具,大都是根据配置者约定了解你打算怎么把一张数据表与你的 Java 对象 映射到一起。默认的 Nutz.Dao 采用 Java 注解(Annotation) 的方式描述这个映射,但是,当然 世界上还有很多其它的映射方式,比如用各种配置文件,比如 JPA 的注解,或者你很想把这个 映射关系写在数据库的几张表里,甚至一个 Excel 表格里(你就觉得这样很酷) 从 1.b.38

  • 下面的代码旨在用给定的分区键和ROWKEY从表中删除一行。但我在Fiddler中得到以下请求/响应。我怎样才能纠正错误? DELETE https://hireazureStorageAcct.table.core.windows.net/mytable(PartitionKey='sample1',%20rowkey='0001')?timeout=20 http/1.1接受:Applicati

  • 我使用的是Spring版本4(Spring data),我想将Object作为JSON返回,我想知道以下代码即使不使用xmlRootElement注释用户类也能工作: 任何机构都可以解释吗?当我需要注释要返回为JSON的对象类时,响应体/响应实体是否自己完成工作?