Spring Data Neo4j(4.2.0.M1)取消节点之间的链接问题

时间:2016-09-26 08:27:11

标签: neo4j relationship spring-data-neo4j spring-data-neo4j-4 unlink

我们正在使用Spring Data Neo4j的4.2.0M1版本(目前是最新版本),当我们尝试从父集合中删除链接的子节点然后通过父存储库保存时,我们遇到了一个问题。

模特课程:

@NodeEntity
public class Movie {

    @GraphId
    private Long graphId;

    private String name;

    /**
     * @return the graphId
     */
    public Long getGraphId() {
        return graphId;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

}

@NodeEntity
public class Actor {

    @GraphId
    private Long graphId;

    private String name;

    @Relationship(type = "ACTS_IN")
    private Set<Movie> movies = new HashSet<>();

    /**
     * @return the graphId
     */
    public Long getGraphId() {
        return graphId;
    }

    /**
     * @return the movies
     */
    public Set<Movie> getMovies() {
        return movies;
    }

    public void addMovie(Movie movie) {
        movies.add(movie);
    }

    public void removeMovie(Movie movie) {
        movies.remove(movie);
    }

    /**
     * @param movies the movies to set
     */
    public void setMovies(Set<Movie> movies) {
        this.movies = movies;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

}

测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader=AnnotationConfigContextLoader.class, classes={RelationAndCacheTest.TestConfiguration.class})
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
public class RelationAndCacheTest {


@Autowired
private ActorRepository actorRepository;

private static Session neo4jSession;

@Configuration
@EnableAutoConfiguration
@EnableTransactionManagement
@EnableExperimentalNeo4jRepositories("com.xxx")
public static class TestConfiguration {

    @Bean
    public org.neo4j.ogm.config.Configuration configuration() {
        org.neo4j.ogm.config.Configuration config = new org.neo4j.ogm.config.Configuration();
        config
        .driverConfiguration()
        .setDriverClassName("org.neo4j.ogm.drivers.http.driver.HttpDriver").setURI("http://localhost:7474");
            return config;
        }

        @Bean
        public SessionFactory sessionFactory() {
            return new SessionFactory(configuration(), "com.xxx") {
                @Override
                public Session openSession() {
                    neo4jSession =  super.openSession();
                    return neo4jSession;
                }
            };
        }

        @Bean
        public Neo4jTransactionManager transactionManager() {
            return new Neo4jTransactionManager(sessionFactory());
        }

    }

    @Test
    public void relationModificationTest() {

        /** Create an actor named Roger and save it => working */
        Actor actor = new Actor();
        actor.setName("Roger");
        actor = actorRepository.save(actor);

        /** Create a movie and link it to the actor by saving it through the actor repository => working */
        Movie movie = new Movie();
        movie.setName("movie");
        actor.addMovie(movie);
        actor = actorRepository.save(actor);

        /** Remove the movie from the actor and save through the actor repository => link not removed !! */
        actor.removeMovie((Movie) actor.getMovies().toArray()[0]);
        actor.setName("bob");
        actor = actorRepository.save(actor);
    }

}

该链接不应被删除?这是一个错误吗?有人面临同样的问题吗?

1 个答案:

答案 0 :(得分:2)

<强> TL; DR

该问题有两种解决方案:

1)注释测试方法@Transactional

2)每次在任何改变它们的操作之前获取对象。

完整解释

SDN 4.1和SDN 4.2在基础OGM Session对象方面的行为存在重要差异。

Session对象的主要作用是跟踪您正在执行的操作,以便在您持久保存对象时确定要在图表上执行哪些操作。它本质上是一个缓存,可以在您完成加载,更新和保存对象的循环时跟踪对象的状态。

在SDN 4.1中,Session没有绑定到Spring事务的生命周期。会话在外部建立事务上下文,会话范围(生命周期)通过使用@Scope注释进行注释来管理,或者通过在需要时以编程方式请求新会话来管理。

在4.2中,Session的生命周期已更改为绑定到发生Repository操作的Spring事务上下文,而后者又与发出请求的线程绑定。为确保此功能始终有效,必须为您创建新的交易(如果尚未启用)。现在,每个新事务都将获得一个新的Session对象。

因此,此代码在4.1中工作而在4.2中不起作用的原因是对ActorRepository的调用之间不再存在任何共享会话。第一次调用存储库的会话信息不适用于第二次(包括关键,哪些关系是新的,哪些关系目前在图中保留),因为它们参与了单独的事务。

4.2的行为发生了变化,因为4.1强制了SDN应用程序的几个限制,以及与Spring框架完全集成的能力。

有关详细信息,请参阅http://graphaware.com/neo4j/2016/09/30/upgrading-to-sdn-42.html,包括从SDN 4.1升级到4.2的步骤