java 如果 Address 嵌套在 User 中,为什么我必须保留两个对象?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12641925/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 09:40:09  来源:igfitidea点击:

Why do I have to persist both objects if Address is nested in User?

javajpa

提问by scarpacci

I am trying to better familiarize myself with JPA so I created a very simple project. I have a User Class and an Address class. It appears that I have to persist both even though I am adding Address to my User class?

我试图更好地熟悉 JPA,所以我创建了一个非常简单的项目。我有一个用户类和一个地址类。即使我将 Address 添加到我的 User 类,我似乎也必须坚持两者?

User:

用户:

import javax.persistence.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Entity
@Table(name = "usr") // @Table is optional, but "user" is a keyword in many SQL variants 
@NamedQuery(name = "User.findByName", query = "select u from User u where u.name = :name")
public class User {
    @Id // @Id indicates that this it a unique primary key
    @GeneratedValue // @GeneratedValue indicates that value is automatically generated by the server
    private Long id;

    @Column(length = 32, unique = true)
    // the optional @Column allows us makes sure that the name is limited to a suitable size and is unique
    private String name;

    // note that no setter for ID is provided, Hibernate will generate the ID for us

    @OneToMany(fetch=FetchType.LAZY, mappedBy="user")
    private List<Address> addresses;

Address:

地址:

@Entity
public class Address {

    @Id // @Id indicates that this it a unique primary key
    @GeneratedValue // @GeneratedValue indicates that value is automatically generated by the server
    private Long id;

    @Column(length=50)
    private String address1;

    @ManyToOne
    @JoinColumn(name="user_id")
    private User user;

EntityManager:

实体管理器:

EntityManager entityManager = Persistence.createEntityManagerFactory("tutorialPU").createEntityManager();

entityManager.getTransaction().begin();

User user = new User();
user.setName("User");

List<Address> addresses = new ArrayList<Address>();
Address address = new Address();
address.setAddress1("Address1");

addresses.add(address);
user.setAddresses(addresses);
entityManager.persist(user);
entityManager.persist(address);
entityManager.getTransaction().commit();
entityManager.close();

Probably doing something wrong...just not sure what it is?

可能做错了什么……只是不确定是什么?

Any suggestions would be appreciated.

任何建议,将不胜感激。

Thanks,

谢谢,

S

回答by Bhesh Gurung

Try the cascadeelement for the annotation.

尝试cascade注释的元素。

@OneToMany(fetch=FetchType.LAZY, mappedBy="user", cascade=CascadeType.PERSIST) 
private List<Address> addresses; 

The documentationsays that by default no operation is cascaded. It also states that the cascade operation is optional, so it really depends on the implementation that you are using.

文件说,在默认情况下没有任何操作,级联。它还指出级联操作是可选的,因此它实际上取决于您使用的实现。

Also, while setting the relationship, make sure you set both sides of the relationship. Set addresses to the user and user to the addresses.

此外,在设置关系时,请确保设置关系的双方。为用户设置地址,将用户设置为地址。

回答by Fritz

What you're talking about it's called Cascading. That means doing the same action to nested objects, such as an Addressin your User. By default, there is no cascading at all if you don't specify any CascadeType.

你所说的就是所谓的级联。这意味着做同样的动作,以嵌套的对象,如Address在你的User。默认情况下,如果您不指定任何CascadeType.

You can define various cascade types at once

您可以一次定义各种级联类型

@OneToMany(fetch=FetchType.LAZY, mappedBy="user", cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
private List<Address> addresses;

or just tell JPA to cascade every operation:

或者只是告诉 JPA 级联每个操作:

@OneToMany(fetch=FetchType.LAZY, mappedBy="user", cascade = CascadeType.ALL)
private List<Address> addresses;

Both ways will result in, for example, a persisted Addresswhile persisting an Useror the deletion of the associated Addresswhen an Useris removed.

这两种方式都会导致,例如,在持久化Address时持久化User或删除关联Address时删除一个User

But!... if you remove CascadeType.REMOVEfrom the first example, removing an Userwon't remove its associated Address(The removal operation won't be applied to nested objects).

但是!...如果您CascadeType.REMOVE从第一个示例中删除,则删除 anUser不会删除其关联Address(删除操作不会应用于嵌套对象)。

回答by sheidaei

You are using a oneToMany annotation. From my understanding you have to persist the parent class (the USer) when you want to add a child class (Address) to it.

您正在使用 oneToMany 注释。根据我的理解,当您想向其添加子类(地址)时,您必须保留父类(用户)。

By persisting the User class, you do let know JPA know which row to update.

通过持久化 User 类,您确实让 JPA 知道要更新哪一行。