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>