【问题标题】:Meaning of mappedBy attribute in an annotation?注释中 mappedBy 属性的含义?
【发布时间】:2012-01-22 17:04:44
【问题描述】:

我是hibernate的新手。我试图在以下代码中创建 Person 和 PersonDetail 实体之间的一对一映射:

@Entity
public class Person {

    private int personId;
    private String personName;
    private PersonDetail personDetail;

    @OneToOne(mappedBy="person")
    public PersonDetail getPersonDetail() {
        return personDetail;
    }

    public void setPersonDetail(PersonDetail personDetail) {
        this.personDetail = personDetail;
    }

    @Id
    @GeneratedValue
    public int getPersonId() {
        return personId;
    }

    public void setPersonId(int personId) {
        this.personId = personId;
    }

    public String getPersonName() {
        return personName;
    }

    public void setPersonName(String personName) {
        this.personName = personName;
    }
}


@Entity
public class PersonDetail {

    private int personDetailId;
    private String zipCode;
    private String job;
    private double income;

    private Person person;

    @OneToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    @Id
    @GeneratedValue
    public int getPersonDetailId() {
        return personDetailId;
    }

    public void setPersonDetailId(int personDetailId) {
        this.personDetailId = personDetailId;
    }

    public String getZipCode() {
        return zipCode;
    }

    public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public double getIncome() {
        return income;
    }

    public void setIncome(double income) {
        this.income = income;
    }

}

我希望 PersonDetail 应该是拥有实体(我知道反之亦然是正确的,但我只是想测试一下)。我不明白的是我放在 Person 实体中的 mappedBy 属性的使用。如果我删除它,我会收到以下错误: “无法确定类型:com.hibernate.onetoonemapping.PersonDetail,在表:Person,列:[org.hibernate.mapping.Column(personDetail)]”

这个 mappedBy 属性有什么作用?我读过 mappedBy 属性放在非拥有方。但它究竟是做什么的呢?

【问题讨论】:

    标签: hibernate jpa


    【解决方案1】:

    这意味着实体之间的关系已经被映射,所以你不要这样做两次。您只需使用 mappedBy 属性说“嘿,它已经完成了”。

    【讨论】:

      【解决方案2】:

      当您想要建立双向关系(可从实体的任一侧访问)时,您在非拥有方使用mappedBy,因为您只能定义一次关系。

      mappedBy 告诉 Hibernate 如何创建实体实例并将数据加载到其中。它应该引用您正在注释的类中的字段名称,在这种情况下为PersonDetail,关系被定义。

      【讨论】:

        【解决方案3】:

        在您的场景中,mappedBy 属性不应该有任何影响。

        我对主键的名称感到困惑(它与“id”不同),但使用非标准名称作为标识符(不知何故符合预期)不会导致您面临的问题。

        我已经在 OneToMany 和 OneToOne 关联的上下文中尝试了 mappedBy 参数,并希望分享我的发现。我有一个类似的场景用于测试目的并说明影响。

        Person.class:

        @Entity
        public class Person {
        
          @Id
          @GeneratedValue
          private Long id;
        
          @Column(name = "name")
          private String name;
        
          @OneToOne
          private Address address;
        }
        

        Address.class(用于 OneToOne 测试):

        @Entity
        public class Address {
          @Id
          @GeneratedValue
          private Long id;
        
          @Column(name = "address")
          private String address;
        
        
          @OneToOne(mappedBy="address")
          private Person person;
        
          @OneToMany(cascade = CascadeType.ALL)
          private Set<Phone> phone = new HashSet<Phone>();
        }
        

        Phone.class(用于 OneToMany 测试):

        @Entity
        public class Phone {
        
          @Id
          @GeneratedValue
          private Long id;
        
          @ManyToOne(optional = false)
          private Person person;
        
          @Column(name = "number")
          private String number;
        }
        

        通过移动 OneToOne 关联的“mappedBy”参数,在任何情况下,hibernate 执行的 sql 语句都保持不变:

        Hibernate: 
        /* insert domain.Address
            */ insert 
            into
                Address
                (id, address) 
            values
                (default, ?)
        Hibernate: 
        /* insert domain.Person
            */ insert 
            into
                Person
                (id, address_id, name) 
            values
                (default, ?, ?)
        

        对于 OneToMany 关联,我发现如果您不指定“mappedBy”,hibernate 会自动使用连接表,而使用“mappedBy”参数,关联会被映射为实体表中的单独列.

        如果我使用...

         @OneToMany(cascade = CascadeType.ALL)
         private Set<Phone> phone = new HashSet<Phone>();
        

        ...用一个电话条目持久化一个人会导致以下语句被执行:

        Hibernate: 
        /* insert domain.Phone
            */ insert 
            into
                Phone
                (id, number, person_id) 
            values
                (default, ?, ?)
        Hibernate: 
        /* insert collection
            row domain.Person.phone */ insert 
            into
                Person_Phone
                (Person_id, phone_id) 
            values
                (?, ?)
        

        而使用...

         @OneToMany(mappedBy="id", cascade = CascadeType.ALL)
         private Set<Phone> phone = new HashSet<Phone>();
        

        导致一种稍微不同的关系模型更接近在这种情况下人们可能期望的:

        Hibernate: 
        /* insert domain.Phone
            */ insert 
            into
                Phone
                (id, number, person_id) 
            values
                (default, ?, ?)
        

        【讨论】:

          猜你喜欢
          • 2017-11-13
          • 2013-08-20
          • 2023-03-29
          • 2012-11-22
          • 2014-11-04
          • 1970-01-01
          • 1970-01-01
          • 2022-06-20
          • 1970-01-01
          相关资源
          最近更新 更多