2011-12-20 24 views
7

Aunque mi pregunta está expresada específicamente sobre la forma en que se representan las relaciones Entity en el marco Play, que utiliza Hibernate, estoy seguro de que esto es general concepto.Intentando comprender la importancia del lado propietario de una relación uno-muchos en ORM

Cuando tenemos una relación de uno a muchos, siempre se nos pide que especifiquemos el lado propietario.

Entonces, por ejemplo, si tuviéramos una relación uno a muchos entre Persona y Número de teléfono, escribiríamos un código como este.

@Entity 
class Person { 
    @OneToMany(mappedBy="person") 
    public Set<PhoneNumber> phoneNumbers; 
} 

@Entity 
class PhoneNumber { 
    @ManyToOne 
    public Person person; 
} 

En el código anterior, la entidad propietaria es PhoneNumber. ¿Cuáles son los pros y los contras de que cada lado sea la entidad propietaria?

Me doy cuenta cuando la entidad propietaria es PhoneNUmber, la relación representada es ManyToOne, que no dará como resultado una tabla de unión, mientras que cuando el lado propietario es Person, la relación representada sería OneToMany, en cuyo caso una tabla de relación ser creado.

¿Es esta la razón principal para determinar el lado propietario, o hay otras razones también?

Actualización: me di cuenta de que this thread proporciona parte de la respuesta, pero estoy esperando que puede haber otros puntos también.

Respuesta

1

Con la mayoría de las capas ORM tiene el concepto de carga diferida. Cuando creas un objeto Persona, no cargará los teléfonos configurados a menos que se te pida. En ocasiones, la forma en que desea buscar datos también puede dictar cómo almacenarlos.

Como si desea mostrar primero la persona y luego mostrar los números de teléfono bajo demanda, entonces mantener las referencias de persona en el teléfono está bien. Primero ejecute una consulta simple para cargar datos de personas y luego solo busque números telefónicos basados ​​en una persona (ya cargada) id (otra consulta simple)

Considerando que para mostrar datos de persona + teléfono de una vez, preferiría tener una tabla de unión donde puede simplemente cargar datos basados ​​en la tabla de persona + tabla de unión de persona-teléfono utilizando la identificación de persona como claves en la tabla de teléfono, todo de una vez. Aquí sería costoso realizar búsquedas sin una tabla de relaciones.

Pero francamente, si se piensa SQL en lugar de ORM entonces se iría con una tabla de relación cada vez: D

+0

Estoy tratando de pensar en voz alta. Digamos que en ambos casos, hacemos una búsqueda ansiosa. Para el primer caso, donde PhoneNumber es la entidad propietaria, activaremos la primera consulta para obtener todas las entidades Persona, y luego activaremos consultas individuales para que cada Persona obtenga todos los PhoneNumber para esa Persona. Sin embargo, si tuviéramos a la Persona como el lado propietario, necesitamos disparar solo una consulta con una combinación. Lo siento si esta es una pregunta tonta, pero ¿no es posible una unión con Person siendo un FK en PhoneNumber? – Parag

+0

Sí, la unión debería ser posible con la identificación de persona FK en la tabla del teléfono también.Aquí estoy (asumiendo) que una búsqueda normalizada sería más rápida, pero debes mirar tu plan de explicación para estar seguro. Otra razón (al menos teórica) para utilizar una tabla de relaciones sería permitir el uso compartido de números de teléfono, como un número de teléfono utilizado por dos personas por turnos. Francamente, cómo funciona una capa de ORM no debe ser relevante para tales consideraciones porque nadie diseña el esquema con una capa de ORM en mente – rjha94

+0

vea mi respuesta en este hilo también por razones de los nombres 'mappedBy' y 'owning side', lo que sucede si no definimos un lado propietario, GOTCHAs - http://stackoverflow.com/questions/2749689/what-is-the-owning-side-in-an-orm-mapping/21068644#21068644 –

6

Un punto importante a tener en cuenta es que la relación propietaria es la que en realidad persiste la relación en guardar. Con un ejemplo:

Person person = new Person(); 
    PhoneNumber pn = new PhoneNumber(); 
    pn.phone = "12345678"; 
    person.phoneNumbers.add(pn); 
    session.save(person); 

la relación no es de hecho ahorrar si vuelve a cargar la entidad de la base de datos verá ningún número. Para agregar realmente la relación que necesita para configurar a la persona en el lado del propietario (PhoneNumber) y luego guardar.

// the relation is not saved 
    Person loadedPerson = (Person)session.load(Person.class, person.id); 
    System.out.println(loadedPerson.phoneNumbers.size()); // prints 0! 

    pn.person = person; 
    session.save(pn); 

    loadedPerson = (Person)session.load(Person.class, person.id); 
    System.out.println(loadedPerson.phoneNumbers.size()); // prints 1 
Cuestiones relacionadas