Значение атрибута mappedBy в аннотации? - PullRequest
6 голосов
/ 22 января 2012

Я новичок в спящем режиме. Я пытался создать взаимно-однозначное сопоставление между сущностью 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 был сущностью-владельцем (я знаю, что, наоборот, это правильно, но я просто хочу проверить). Что я не понимаю, так это использование атрибута mappedBy, который я поместил в сущность Person. Если я удаляю его, я получаю следующую ошибку: "Не удалось определить тип для: com.hibernate.onetoonemapping.PersonDetail, в таблице: Person, для столбцов: [org.hibernate.mapping.Column (personDetail)]] *

Что делает этот атрибут mappedBy? Я читал, что атрибут mappedBy находится на стороне, не являющейся владельцем. Но что именно он делает?

Ответы [ 3 ]

9 голосов
/ 22 января 2012

Это означает, что это отношение между объектами уже отображено, поэтому вы не делаете этого дважды. Вы просто говорите: «Эй, все готово», используя атрибут mappedBy.

7 голосов
/ 20 сентября 2012

Когда вы хотите сделать отношение двунаправленным (доступным с любой стороны объекта), вы использовали mappedBy на стороне, не являющейся собственником, потому что вы можете определить отношение только один раз.

mappedBy сообщает Hibernate, как создавать экземпляры ваших сущностей и загружать в них данные. Он должен ссылаться на имя поля в классе, который вы аннотируете, PersonDetail в этом случае, где определена связь.

3 голосов
/ 20 сентября 2012

В вашем сценарии атрибут mappedBy не должен оказывать никакого влияния.

Я был озадачен именем первичного ключа (оно отличается от "id"), но использование нестандартного имени в качестве идентификатора (каким-то образом, как и ожидалось) не вызывает проблемы, с которой вы сталкиваетесь.

Я экспериментировал с параметром mappedBy в контексте ассоциаций OneToMany и OneToOne и хотел бы поделиться своими выводами. У меня есть похожий сценарий для целей тестирования и для иллюстрации воздействия.

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

Перемещая параметр «mappedBy» для ассоциации OneToOne, в любом случае операторы sql, выполняемые hibernate, оставались прежними:

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, ?, ?)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...