【问题标题】:JPA/Hibernate cascading persist doesn't workJPA/Hibernate 级联持久性不起作用
【发布时间】:2018-01-02 04:31:47
【问题描述】:

我在将持久操作级联到子级时遇到问题。

我有一个 parent 和一个 child 类。当我用 Spring-Data Repository 保存一个孩子的父母时,孩子的值都是 null 或 0。

如果我将 CascadeType.ALL 添加到 OneToMany-Annotation 我收到此错误: “正在合并同一实体的多个表示”

@Entity
@Getter
@Setter
public class TestParent {
    @Id
    @GeneratedValue
    private Long id;

    @OneToMany(mappedBy = "parent", cascade = {CascadeType.DETACH, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.REMOVE}, orphanRemoval = true)
    private List<TestChild> children;
}

@Entity
@Getter
@Setter
public class TestChild {
    @Id
    @GeneratedValue
    private Long id;

    private int value;

    @ManyToOne
    private TestParent parent;
}

这是测试保存对象是否有效的代码:

@Test
@Transactional
public void test123(){
    TestParent parent = new TestParent();
    parent = testRepo.save(parent);

    TestChild child1 = new TestChild();
    child1.setValue(3);
    child1.setParent(parent);
    parent.setChildren(new ArrayList<>());
    parent.getChildren().add(child1);

    parent = testRepo.save(parent);

    assertThat(parent.getChildren().size()).isNotZero();
    assertThat(parent.getChildren().get(0).getValue()).isEqualTo(3);
}

所以我的方法是在不添加 cascadeType Merge 的情况下修复级联 Persist。任何提示我做错了什么?

【问题讨论】:

  • 然后不要保存父级。第二次保存是更新,因此是合并。持久化仅对新的非持久化实例有效。接下来,您将通过在添加子项之前执行 new ArrayList() 来销毁托管集合。恕我直言,您的代码在多个方面存在缺陷。

标签: java spring hibernate jpa


【解决方案1】:

如果您想了解有关将实体映射到 DB 的知识,First Hibernate User Guide 是一个很好的资源。

我检查了您的示例,它可以在我的机器 (TM) 上使用以下 repo 声明:

public interface PersonRepository extends CrudRepository<HibernateProxyDemoApplication.TestParent, Long> {  }

还有spring boot应用:

@SpringBootApplication
@EnableJpaRepositories // just to make sure
public class HibernateProxyDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(HibernateProxyDemoApplication.class, args);
    }
...
}

和pom.xml:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.4.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

我只能建议你先删除 Lombok 注释 (@Getter/@Setter) 并手动编写 getter/setter,然后看看你的程序可能有什么问题。

附言。它也适用于级联 ALL

【讨论】:

  • 我现在还用 spring-boot 1.5.5 创建了一个新的 SpringBootApplication。 (在我使用 1.4.4 之前)。但它不起作用。我的 gradle 依赖项是:spring-boot-starter-data-jpa、mysql-connector-java、spring-boot-starter-test
  • 感谢您的提示。升级到 spring-boot 1.5.5 并使用 Cascade ALL 终于奏效了。使用新的 spring 版本,我不再收到错误“同一实体的多个表示正在合并”
猜你喜欢
  • 2018-05-15
  • 1970-01-01
  • 1970-01-01
  • 2017-08-18
  • 2013-10-26
  • 2014-09-08
  • 2010-10-24
  • 1970-01-01
相关资源
最近更新 更多