spring-data-neo4j:无法使用相同的标签创建两个关系属性

时间:2015-02-21 02:59:52

标签: spring-data-neo4j

使用spring-data-neo4j,我无法在具有相同标签的同一个类中设置两个关系属性。

以下代码可以在我的分支https://github.com/spencerhrob/gs-accessing-data-neo4j/tree/same-name-relationships中找到。

Person.java:

@NodeEntity
public class Person {

    @GraphId Long id;
    public String name;

    public Person() {}
    public Person(String name) { this.name = name; }

    @RelatedTo(type="MEMBER_OF", direction=Direction.OUTGOING)
    Dojo dojo;

    @RelatedTo(type="MEMBER_OF", direction=Direction.OUTGOING)
    MailingList mailingList;

    public void setDojo(Dojo dojo) {
        this.dojo = dojo;
    }
    public void setMailingList(MailingList mailingList) {
        this.mailingList = mailingList;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + "]";
    }
}

Dojo.java:

@NodeEntity
public class Dojo {

    @GraphId Long id;
    public String name;

    public Dojo() { }
    public Dojo(String name) { this.name = name; }

    @Override
    public String toString() {
        return "Dojo [name=" + name + "]";
    }
}

MailingList.java:

@NodeEntity
public class MailingList {

    @GraphId Long id;
    public String name;

    public MailingList() { }
    public MailingList(String name) { this.name = name; }

    @Override
    public String toString() {
        return "MailingList [name=" + name + "]";
    }

}

Application.java:

@Configuration
@EnableNeo4jRepositories(basePackages = "hello")
public class Application extends Neo4jConfiguration implements CommandLineRunner {

    public Application() {
        setBasePackage("hello");
    }

    @Bean
    GraphDatabaseService graphDatabaseService() {
        return new GraphDatabaseFactory().newEmbeddedDatabase("accessingdataneo4j.db");
    }

    @Autowired
    PersonRepository personRepository;

    @Autowired
    GraphDatabase graphDatabase;

    public void run(String... args) throws Exception {
        Transaction tx = graphDatabase.beginTx();
        try {
            Person linus = new Person("Linus");
            linus.setDojo(new Dojo("Coding Dojo"));
            linus.setMailingList(new MailingList("Kernel Mailing List"));

            personRepository.save(linus);

            tx.success();
        } finally {
            tx.close();
        }
    }

    public static void main(String[] args) throws Exception {
        FileUtils.deleteRecursively(new File("accessingdataneo4j.db"));

        SpringApplication.run(Application.class, args);
    }
}

当我运行此代码时,我得到以下异常:

  

java.lang.IllegalStateException:无法执行CommandLineRunner     在   org.springframework.boot.SpringApplication.runCommandLineRunners(SpringApplication.java:680)     在   org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:695)     在   org.springframework.boot.SpringApplication.run(SpringApplication.java:321)     在   org.springframework.boot.SpringApplication.run(SpringApplication.java:952)     在   org.springframework.boot.SpringApplication.run(SpringApplication.java:941)     at hello.Application.main(Application.java:56)引起:   org.springframework.data.mapping.model.MappingException:设置   属性mailingList到Person [name = Linus] at的Dojo [name = null]   org.springframework.data.neo4j.support.mapping.SourceStateTransmitter.setProperty(SourceStateTransmitter.java:85)     在   org.springframework.data.neo4j.support.mapping.SourceStateTransmitter.copyEntityStatePropertyValue(SourceStateTransmitter.java:91)     在   org.springframework.data.neo4j.support.mapping.SourceStateTransmitter.access $ 000(SourceStateTransmitter.java:40)     在   org.springframework.data.neo4j.support.mapping.SourceStateTransmitter $ 2.doWithAssociation(SourceStateTransmitter.java:61)     在   org.springframework.data.mapping.model.BasicPersistentEntity.doWithAssociations(BasicPersistentEntity.java:324)     在   org.springframework.data.neo4j.support.mapping.SourceStateTransmitter.copyPropertiesFrom(SourceStateTransmitter.java:57)     在   org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.loadEntity(Neo4jEntityConverterImpl.java:112)     在   org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.read(Neo4jEntityConverterImpl.java:104)     在   org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister $ CachedConverter.read(Neo4jEntityPersister.java:170)     在   org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.createEntityFromState(Neo4jEntityPersister.java:189)     在   org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:244)     在   org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:231)     在   org.springframework.data.neo4j.support.Neo4jTemplate.save(Neo4jTemplate.java:356)     在   org.springframework.data.neo4j.support.Neo4jTemplate.save(Neo4jTemplate.java:350)     在   org.springframework.data.neo4j.repository.AbstractGraphRepository.save(AbstractGraphRepository.java:91)     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)     在   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)     在java.lang.reflect.Method.invoke(Method.java:606)at   org.springframework.data.repository.core.support.RepositoryFactorySupport $ QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:405)     在   org.springframework.data.repository.core.support.RepositoryFactorySupport $ QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:390)     在   org.springframework.data.repository.core.support.RepositoryFactorySupport $ QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:344)     在   org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)     在   org.springframework.transaction.interceptor.TransactionInterceptor $ 1.proceedWithInvocation(TransactionInterceptor.java:98)     在   org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)     在   org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)     在   org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)     在   org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)     在   org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)     在   org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)     在com.sun.proxy。$ Proxy43.save(未知来源)at   hello.Application.run(Application.java:44)at   org.springframework.boot.SpringApplication.runCommandLineRunners(SpringApplication.java:677)     ...省略了5个常见帧引起的:   org.springframework.core.convert.ConverterNotFoundException:没有   转换器发现能够从类型hello.Dojo转换为类型   hello.MailingList at   org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:291)     在   org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:177)     在   org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:158)     在   org.springframework.data.mapping.model.BeanWrapper.getPotentiallyConvertedValue(BeanWrapper.java:155)     在   org.springframework.data.mapping.model.BeanWrapper.setProperty(BeanWrapper.java:75)     在   org.springframework.data.neo4j.support.mapping.SourceStateTransmitter.setProperty(SourceStateTransmitter.java:83)     ...省略了37个常见帧

那里有很多,但真正的错误是Spring试图将Dojo转换为MailingList。

同时,如果我用不同的名称命名关系(如在我的分支https://github.com/spencerhrob/gs-accessing-data-neo4j/tree/different-name-relationships中),则此代码有效。 Person.java:

@NodeEntity
public class Person {

    @GraphId Long id;
    public String name;

    public Person() {}
    public Person(String name) { this.name = name; }

    @RelatedTo(type="MEMBER_OF_DOJO", direction=Direction.OUTGOING)
    Dojo dojo;

    @RelatedTo(type="MEMBER_OF_LIST", direction=Direction.OUTGOING)
    MailingList mailingList;

    public void setDojo(Dojo dojo) {
        this.dojo = dojo;
    }
    public void setMailingList(MailingList mailingList) {
        this.mailingList = mailingList;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + "]";
    }
}

对Application.java(或Dojo.java或MailingList.java)没有任何更改,此代码成功执行。

我从这个例子中理解,spring-data-neo4j不允许类具有两个具有相同标签的属性。在某些情况下,不同的关系需要具有相同的标签 - 例如,符合建模标准。是否可以在spring-data-neo4j中设置多个具有相同名称的关系?如果是这样,怎么样?

1 个答案:

答案 0 :(得分:0)

我找到了这个问题的答案。我所寻找的是“enforceTargetType”属性described in the documentation

我已经使用此修复程序创建了一个存储库的分支。它位于https://github.com/spencerhrob/gs-accessing-data-neo4j/tree/same-name-enforce-target

Person.java:

@NodeEntity
public class Person {

    @GraphId Long id;
    public String name;

    public Person() {}
    public Person(String name) { this.name = name; }

    @RelatedTo(type="MEMBER_OF", direction=Direction.OUTGOING, enforceTargetType=true)
    Dojo dojo;

    @RelatedTo(type="MEMBER_OF", direction=Direction.OUTGOING, enforceTargetType=true)
    MailingList mailingList;

    public void setDojo(Dojo dojo) {
        this.dojo = dojo;
    }
    public void setMailingList(MailingList mailingList) {
        this.mailingList = mailingList;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + "]";
    }
}

在没有对存储库进行其他更改的情况下,此代码运行时没有任何错误,并且检查创建的Neo4j数据库显示它的行为符合预期。