[英]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 个类Parent
和Child
,关系的所有者是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.