java - Spring JPA在多对多关系中持久化子级时如何持久化父级

标签 java spring hibernate jpa

我有一个具有多对多关系的基本项目。有2个类ParentChild,关系的所有者是类Parent。当父实体被持久化时,子实体也会被持久化(这是期望的行为)。但相反,当子实体被持久化时,父实体不会被持久化。

如何让父实体与子实体同时保留?下面的代码给出了允许重现问题的 spring-boot 类,在 logger.info("---> 2nd fetch allparents"); 之后,我期望有 5 个 parent ,但我有只有两个。

这是我的实体类:

@Entity
public class Parent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String name;

    // @JoinTable => owner of the relationship
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "parent_child",
            joinColumns = @JoinColumn(name = "parent_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "child_id", referencedColumnName = "id"))
    private Set<Child> children;
}

@Entity
public class Child {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String name;

    @ManyToMany(mappedBy = "children")
    private Set<Parent> parents;

    // getters and setters
}

存储库

public interface ChildRepository extends JpaRepository<Child, Long> {}
public interface ParentRepository extends JpaRepository<Parent, Integer> {}

springboot应用

@SpringBootApplication
public class Application implements CommandLineRunner {
    private static final Logger logger = LoggerFactory.getLogger(Application.class);

    @Autowired
    private ParentRepository parentRepository;

    @Autowired
    private ChildRepository childRepository;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    @Transactional
    public void run(String... strings) throws Exception {
        // save a couple of parents
        Child childA = new Child("Child A"); Child childB = new Child("Child B"); Child childC = new Child("Child C");
        Parent parentA = new Parent("Parent A", new HashSet<>(Arrays.asList(childA, childB))); Parent parentB = new Parent("Parent B", new HashSet<>(Arrays.asList(childA, childC)));
        parentRepository.saveAll(Arrays.asList(parentA, parentB));

        // fetch all parents
        logger.info("---> 1st fetch all parents");
        for (Parent parent : parentRepository.findAll()) {
            logger.info(parent.toString());
        }

        // save a couple of children
        Parent parentD = new Parent("Parent D"); Parent parentE = new Parent("Parent E"); Parent parentF = new Parent("Parent F");
        Child childD = new Child("Child D", new HashSet<Parent>(Arrays.asList(parentD, parentE))); Child childE = new Child("Child E", new HashSet<Parent>(Arrays.asList(parentE, parentF)));
        childRepository.saveAll(Arrays.asList(childD, childE));

        // fetch all children
        logger.info("---> 1st fetch all children");
        for (Child child : childRepository.findAll()) {
            logger.info(child.toString());
        }

        // fetch all parents
        logger.info("---> 2nd fetch all parents");
        for (Parent parent : parentRepository.findAll()) {
            logger.info(parent.toString());
        }

        // fetch all children
        logger.info("---> 2nd fetch all children");
        for (Child child : childRepository.findAll()) {
            logger.info(child.toString());
        }
    }
}

最佳答案

使用 JPA,当您想要将更新传播到关系项时,您必须指定要应用的传播类型。

因此,当您定义关系ManyToMany时,您可以添加级联类型“PERSIST”来传播实体Parent的指令INSERT

@ManyToMany(mappedBy = "children", cascade = CascadeType.PERSIST)
private Set<Parent> parents;

这里是 Hibernate 的完整规范Springboot使用

如果您使用注释,您可能已经注意到级联属性将 CascadeType 数组作为值。 JPA 中的级联概念与上面描述的操作的传递持久性和级联非常相似,但语义和级联类型略有不同:

  • CascadeType.PERSIST :将持久(创建)操作级联到 关联实体 persist() 被调用或者实体被管理
  • CascadeType.MERGE :将合并操作级联到关联的 实体(如果调用 merge() 或实体受管理)
  • CascadeType.REMOVE :将删除操作级联到关联的 实体(如果调用了delete())
  • CascadeType.REFRESH :级联 如果调用了refresh(),则对关联实体进行刷新操作
  • CascadeType.DETACH :将分离操作级联到关联的 实体,如果 detach() 被调用 CascadeType.ALL:以上所有

关于java - Spring JPA在多对多关系中持久化子级时如何持久化父级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57524653/

相关文章:

java - 如何在 Spring RequestHandlerRetryAdvice 中以指数方式增加重试间隔

java - Kotlin包级别的Hibernate TypeDefs

java - Hibernate,集合,仅保存某些属性

java - 难以使用 SimpleDateFormat 解析字符串

java - Apache Spark 作业因 FileNotFoundExceptoin 而失败

java - 带有数据透视表的高级 JPA

java - Hibernate 实体中的复杂关系

java - 我应该如何继续制作具有拖动功能和图形箭头的交互式程序

java - 单击按钮时发送自动短信

spring - 如何使用 XML 配置在 Spring 中将多个包传递给 packagesToScan 属性