Spring Data Neo4j 4: ошибка при обновлении свойства до нуля?

Я использую Spring Data Neo4j 4 GraphRepository для сохранения и извлечения данных. Использование методов GraphRepository save() и findAll().

Когда я обновляю существующее свойство сущности до нуля, кажется, что изменения не отражаются в возвращаемых данных.

Если я обновлю свойство до любого другого значения, отличного от null, изменения отразятся правильно.

Я вижу, что обновление нулевого свойства выполняется на сервере БД. Но метод findAll() не отражает изменения и сохраняет старое значение.

Это известная ошибка? Любое обходное решение? Или это какая-то проблема с кэшированием?

ОБНОВЛЕНИЕ

Попытавшись понять, что происходит, я обнаружил, что эта проблема возникает, когда у вас есть два разных объекта 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();
}

person Martin L.    schedule 14.12.2015    source источник


Ответы (2)


Если вы используете персистентность в области HttpSession в SDN, вы должны убедиться, что объекты, привязанные к вашему контроллеру через @ModelAttribute, имеют ту же область, что и слой персистентности. Для этого используйте аннотацию @SessionAttribute на контроллере.

Если вы используете объекты с HttpRequest областью действия в своем контроллере и HttpSession-scoped постоянство, вы получите разные объекты, представляющие один и тот же объект графа на веб-уровне, и это запутает механизм сохранения.

person Vince    schedule 17.12.2015

Не должно быть проблемой вообще. я только что попробовал

@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, никогда не должно устанавливаться вручную, т. е. через ваш код. Вы должны загрузить объект по идентификатору, когда вам требуется его обновить. Это гарантирует, что объект известен контексту отображения OGM и правильно управляется.

person Luanne    schedule 15.12.2015
comment
Я добавил пример кода, чтобы вы видели, в каком случае возникает проблема. Дайте мне знать, если у вас есть какие-либо идеи, как справиться с этим. Спасибо. - person Martin L.; 16.12.2015
comment
Хорошо, я вижу. Итак, есть ли в этом случае чистый способ заставить Spring MVC @ModelAttribute работать с SDN? Новые экземпляры объектов создаются, а затем заполняются при использовании аннотации @ModelAttribute, поэтому это всегда будет приводить к этой проблеме... - person Martin L.; 16.12.2015