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

Spring Data Neo4j (4.2.0.M1) Unlink issue between nodes

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

型号CLASSES:

@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;
    }

}

测试 CLASS:

@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);
    }

}

link 不应该被删除?这是一个错误吗?有人遇到同样的问题吗?

TL;DR

问题有两种解决方法:

1) 注释测试方法@Transactional

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

完整解释

关于底层 OGM Session 对象,SDN 4.1 和 SDN 4.2 的行为存在重要差异。

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

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

在 4.2 中,会话的生命周期已更改为绑定到发生存储库操作的 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 的步骤