2015-12-14 33 views
0

我使用Spring Data Neo4j 4 GraphRepository来保存和检索数据。使用GraphRepository save()和findAll()方法。Spring Data Neo4j 4:将属性更新为null时出错?

当我更新一个现有的实体属性为null时,似乎更改不反映在返回的数据。

如果我将该属性更新为任何其他非空值,则更改将被正确反映。

我可以看到在数据库服务器上执行了空属性更新。但findAll()方法不反映更改并保留旧值。

这是一个已知的错误吗?任何解决方法?或者它是某种缓存问题?

UPDATE

试图了解发生了什么之后,我发现,当你有同一个实体的两个不同的Java对象会出现此问题。 null属性将永远不会被更新(但其他属性将使用非空值)。

示例代码:

@Autowired 
MovieRepository repository; 

public void test() { 
    repository.deleteAll(); 

    Movie movie1 = new Movie(); 
    movie1.setName("Pulp Fiction"); 
    movie1.setDirector("Quentin Tarantino"); 
    movie1 = repository.save(movie1); 

    System.out.println("Movie1: " + movie1); 

    Movie movie2 = new Movie(); 
    movie2.setId(movie1.getId()); 
    movie2.setName(movie1.getName()); 
    movie2.setDirector(null); // implicit... 
    movie2 = repository.save(movie2); 

    System.out.println("Movie2: " + movie2); 

    Movie movie3 = repository.findOne(movie1.getId()); 
    System.out.println("Movie3: " + movie3); 
} 

真实案例:使用SDN与Spring MVC的表单时,它看起来像实体从模型创建的属性。当表单中的值设置为null时,更新在Neo4j中正确执行,但使用任何find ...()方法时不会正确返回值。因此它会导致陈旧的数据。

备注:当Neo4J会话作用域是每个“会话”时发生此问题,而当会话作用域是每个“请求”时不会发生此问题。

@Bean 
@Override 
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS) 
public Session getSession() throws Exception { 
    return super.getSession(); 
} 

回答

1

如果您在SDN中使用HttpSession范围的持久性,您应确保通过@ModelAttribute绑定到控制器的对象与持久层具有相同的范围。使用控制器上的@SessionAttribute注释来实现此目的。

如果在控制器和持久性中使用HttpRequest -scoped对象,则会在Web层获得表示相同图形实体的不同对象,这会混淆持久性机制。

0

应该不是问题。我刚试过

@Test 
public void shouldPersistNulls() { 
     TempMovie movie = new TempMovie("Pulp Fiction"); 

     tempMovieRepository.save(movie); 

     assertSameGraph(getDatabase(), "CREATE (m:Movie {name:'Pulp Fiction'})"); 

     TempMovie loadedMovie = tempMovieRepository.findAll().iterator().next(); 
     loadedMovie.setName(null); 
     tempMovieRepository.save(loadedMovie); 

     assertSameGraph(getDatabase(), "CREATE (m:Movie)"); 

     TempMovie loadedAgainMovie = tempMovieRepository.findAll().iterator().next(); 
     assertNull(loadedAgainMovie.getName()); 
    } 

它通过了。基于编辑的问题

更新

代表@GraphId的属性必须从未手动即通过代码中设置。当您需要更新它时,您应该通过id加载实体。这确保了该实体对OGM的映射上下文是已知的并且被正确管理。

+0

我添加了一个代码示例,供您查看发生问题的情况。如果您有任何想法如何处理这个问题,请告诉我。谢谢。 –

+0

好吧,我明白了。那么是否有任何“干净”的方式来使Spring MVC'@ ModelAttribute'在这种情况下与SDN协同工作?新的对象实例被创建,然后在使用'@ ModelAttribute'注释时被填充,所以它总会导致这个问题... –