注释中mappedBy属性的含义?

时间:2012-01-22 17:04:44

标签: hibernate jpa

我是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,for columns:[org.hibernate.mapping.Column(personDetail)]”

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

2 个答案:

答案 0 :(得分:9)

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

答案 1 :(得分: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, ?, ?)