2012-01-22 10 views
6

Soy un novato en Hibernate. Yo estaba tratando de crear un uno-a-uno entre la persona y la entidad PersonDetail en el siguiente código:Significado del atributo mappedBy en una anotación?

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

} 

Quiero que PersonDetail debe ser la entidad propietaria (Sé que viceversa es correcta, pero sólo quiero probar). Lo que no entiendo es el uso del atributo mappedBy que puse en la entidad Person. Si lo elimino, aparece el siguiente error: "No se pudo determinar el tipo para: com.hibernate.onetoonemapping.PersonDetail, en la tabla: Persona, para las columnas: [org.hibernate.mapping.Column (personDetail)]"

¿Qué hace este atributo mappedBy? He leído que el atributo mappedBy se coloca en el lado no propietario. Pero, ¿qué es exactamente lo que hace?

Respuesta

7

Significa que esa relación entre entidades ya ha sido asignada, por lo que no lo hace dos veces. Solo di "Oye, está terminado" usando el atributo mappedBy.

3

En su escenario, el atributo mappedBy no debería tener ningún impacto.

Estaba confundido acerca del nombre de la clave principal (es diferente de "id"), pero usar un nombre no estándar como identificador (de alguna manera como se esperaba) no causa el problema al que se enfrenta.

He experimentado con el parámetro mappedBy en el contexto de las asociaciones OneToMany y OneToOne y me gustaría compartir mis hallazgos. Tengo un escenario similar para fines de prueba y para ilustrar el impacto.

Person.class:

@Entity 
public class Person { 

    @Id 
    @GeneratedValue 
    private Long id; 

    @Column(name = "name") 
    private String name; 

    @OneToOne 
    private Address address; 
} 

Address.class (por OneToOne pruebas):

@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 (por OneToMany pruebas):

@Entity 
public class Phone { 

    @Id 
    @GeneratedValue 
    private Long id; 

    @ManyToOne(optional = false) 
    private Person person; 

    @Column(name = "number") 
    private String number; 
} 

Al desplazarse por el "mapp" edBy" parámetro para la asociación OneToOne, en cualquier caso, las sentencias SQL ejecutadas por hibernación sigue siendo el mismo:

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

Para OneToMany asociaciones He descubierto que si no se especifica 'mappedBy' hibernación de forma automática utiliza una tabla de unión , mientras que con el parámetro "mappedBy" la asociación se correlaciona como una columna separada en la tabla de entidades.

Si utilizo ...

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

... persising una persona con un teléfono de entrada de resultados en las siguientes sentencias que se ejecutan:

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 
     (?, ?) 

Mientras que el uso de ...

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

resultados en un modelo relacional ligeramente diferente que está más cerca de lo que sería una posible esperar en este caso:

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

Cuando se quiere hacer una relación bidireccional (accesible desde cualquier lado de la entidad) usaste mappedBy en el lado no propietario porque solo puedes definir la relación una vez.

mappedBy le dice a Hibernate cómo crear instancias de sus entidades y cargar los datos en ellas. Debe referirse al nombre del campo en la clase que está anotando, PersonDetail en esta instancia, donde se define la relación.

Cuestiones relacionadas