简体   繁体   English

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

[英]Spring JPA how to persist parent when the child is persisted in ManyToMany relationship

I have a basic project with a many to many relationship.我有一个具有多对多关系的基本项目。 There are 2 classes Parent and Child , the owner of the relationship is the class Parent .有 2 个类ParentChild ,关系的所有者是Parent类。 When parent entities are persisted child entities are also persisted (which is the desired behavior).当父实体被持久化时,子实体也被持久化(这是所需的行为)。 But at the opposite when the child entities are persisted, the parent entities are not persisted.但相反,当子实体被持久化时,父实体不会被持久化。

How do I get the parent entities persisted at the same time than the child entities?如何让父实体与子实体同时保留? The code below give the spring-boot class that allow to reproduce the issue, after the logger.info("---> 2nd fetch all parents");下面的代码给出了允许重现问题的 spring-boot 类,在logger.info("---> 2nd fetch all parents"); I expect to have 5 parents but I have only two.我希望有 5 个父母,但我只有两个。

Here are my entity classes :这是我的实体类:

@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
}

The repositories存储库

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

The springboot application 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());
        }
    }
}

With JPA when you want to propagated an update to a relational item you have to specify the type of propagation you want to apply.使用 JPA,当您想要将更新传播到关系项时,您必须指定要应用的传播类型。

So when you define a relation ManyToMany you can add the cascade type "PERSIST" to propagate the instruction INSERT for the entity Parent因此,当您定义关系ManyToMany 时,您可以添加级联类型“PERSIST”来传播实体父级的指令 INSERT

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

Here the complete specification for Hibernate used by Springboot这里是 Springboot 使用的Hibernate的完整规范

In case you are using annotatons you probably have noticed the cascade attribute taking an array of CascadeType as a value.如果您正在使用注释,您可能已经注意到将 CascadeType 数组作为值的级联属性。 The cascade concept in JPA is very is similar to the transitive persistence and cascading of operations as described above, but with slightly different semantics and cascading types: JPA 中的级联概念与上述操作的传递持久性和级联非常相似,但语义和级联类型略有不同:

  • CascadeType.PERSIST : cascades the persist (create) operation to associated entities persist() is called or if the entity is managed CascadeType.PERSIST :将持久(创建)操作级联到关联实体persist() 被调用或实体是否被管理
  • CascadeType.MERGE : cascades the merge operation to associated entities if merge() is called or if the entity is managed CascadeType.MERGE :如果调用了 merge() 或者实体被管理,则将合并操作级联到关联的实体
  • CascadeType.REMOVE : cascades the remove operation to associated entities if delete() is called CascadeType.REMOVE :如果 delete() 被调用,则将删除操作级联到关联的实体
  • CascadeType.REFRESH : cascades the refresh operation to associated entities if refresh() is called CascadeType.REFRESH :如果调用 refresh() ,则将刷新操作级联到关联的实体
  • CascadeType.DETACH : cascades the detach operation to associated entities if detach() is called CascadeType.ALL: all of the above CascadeType.DETACH :如果 detach() 被调用,则将分离操作级联到关联的实体 CascadeType.ALL:以上所有

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Spring 数据 JPA 和 hibernate 分离的实体传递以保持多对多关系 - Spring data JPA and hibernate detached entity passed to persist on ManyToMany relationship Spring boot JPA:删除多对一关系的父实体时如何保留子实体? - Spring boot JPA: How to keep the child entity when deleting the parent entity in a many-to-one relationship? 当子实体与父实体之间具有一对一的JPA关系时,可以持久保留子实体和父实体吗? - Is it ok to persist the Child entity along with the Parent entity when having a One-To-One JPA relationship in between them? 调用父persist方法时,JPA子节点不会持久存在 - JPA child doesn't persist when parent persist method is called Spring JPA中的“ ManyToMany”关系问题 - Issue with “ManyToMany” relationship Spring JPA @ManyToMany无法使用Spring / JPA / REST从子级到父级工作 - @ManyToMany is not working from Child-to-Parent using Spring/JPA/REST 执行查询时多对多关系不起作用(Spring Data JPA) - ManyToMany relationship not working when executing query (Spring Data JPA) Spring Data Jpa项目使用ManyToMany关系时的生成查询 - Generation query when the ManyToMany relationship is used by Spring Data Jpa project JPA保留了来自ManyToMany关系的已经保留的对象 - JPA persists already persisted Objects from a ManyToMany relationship JPA父母子女关系 - JPA parent child relationship
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM