当前位置: 首页 > 知识库问答 >
问题:

Spring数据Neo4j 4:将属性更新为null时出现错误?

宦烈
2023-03-14

我使用Spring Data Neo4j 4 GraphRepository来保存和检索数据。使用GraphRepository保存()和findAll()方法

当我将现有实体属性更新为null时,所做的更改似乎不会反映在返回的数据中。

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

我可以看到null属性更新是在DB服务器上执行的。但是findAll()方法不反映更改并保留旧值。

这是已知的bug吗?有解决办法吗?还是某种缓存问题?

使现代化

在试图理解发生了什么之后,我发现当同一个实体有两个不同的Java对象时,就会出现这个问题。null属性将永远不会更新(但具有非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中正确执行,但是当使用任何查找...()方法时,这些值不会正确返回。因此,它会导致过时的数据。

附带说明:当Neo4J会话范围是每个会话时会出现此问题,而当会话范围是每个请求时则不会出现此问题。

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

共有2个答案

马欣德
2023-03-14

这根本不是问题。我刚试过

@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的映射上下文知道实体并正确管理。

洪鸿博
2023-03-14

如果您在SDN中使用Http会话范围的持久性,您应该确保通过@模型属性绑定到Controller的对象具有与持久性层相同的范围。使用Controller上的@SessionAtinn注释来实现这一点。

如果在控制器中使用HttpRequest-作用域对象和HttpSession作用域持久化,则将在web层获得表示相同图形实体的不同对象,这将混淆持久化机制。

 类似资料:
  • 在下面的代码中,的最后两个引用由Resharper标记,尽管Resharper应该知道不会为空。 首先,字符串属性检查为空、空或空白,如果这些条件中的任何一个为真,则跳过该块。扩展方法,仅在输入为Null时返回Null,并且这被标记为注释(第二个代码块)。因为我们已经检查了属性是否为非空,并且扩展方法被标记为返回非空,所以我希望Resharper知道为非空。 上面这两行是标记

  • 问题内容: 这是我的代码,直接来自一个类。我的问题是第22行在。 我看不到问题,这是Zend Engine的限制吗?还是我瞎了。 问题答案: 在5.6之前的PHP版本中初始化类属性时,不能使用 非常量值 。 这些是在编译时初始化的,在编译时PHP将不进行任何计算或执行任何代码。是需要评估的表达式,您不能在那里进行评估。可以将其替换为常数,也可以在中进行计算。 2014年推出的PHP 5.6 允许“

  • 我正在尝试将与spring-data-jdbc和PostgreSQL数据库结合使用,以跟踪首次创建表条目的时间。当插入新行时,这有效(它正确地将其设置为当前日期),但是在更新条目时,我得到异常,因为它被设置为null,这是我的配置不允许的。 这是我的实体(省略了其他不相关的字段): 这是我的存储库: 这是相关的配置: 使用方法,第一次正确设置了。当使用相同的方法更新现有实体时,当我希望跳过字段时,

  • 我想用Java更新时区数据。据我所知,可以使用解决这个问题。但我发现了错误: Java版本为: 怎么了?

  • 只有当新项目的日期比现有项目更近时,我才想更新DynamoDB中的项目。目前,我正在查询现有项目,在代码中进行比较,然后写入数据库。我想知道是否有办法让DynamoDB为我进行检查。我已经研究过使用预期,但是它的比较运算符需要引入一个参数,这违背了目的,因为这意味着无论如何都必须查询现有项目。 我和8Java一起工作。