2015-12-14 88 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'註釋時被填充,所以它總會導致這個問題... –