2010-06-24 23 views
80

Ok, así que esta es probablemente una pregunta trivial, pero estoy teniendo problemas para visualizar y entender las diferencias y cuándo usar cada una. También estoy un poco confuso en cuanto a cómo los conceptos como mapeos unidireccionales y bidireccionales afectan las relaciones uno a muchos/muchos a muchos. Estoy usando Hibernate en este momento, por lo que cualquier explicación relacionada con ORM será útil.Diferencia entre uno-a-muchos, muchos-a-uno y muchos-a-muchos?

A modo de ejemplo digamos que tengo el siguiente configuración:

public class Person{ 
    private Long personId; 
    private Set<Skill> skills; 
    //Getters and setters 
} 

public class Skill{ 
    private Long skillId; 
    private String skillName; 
    //Getters and setters 
} 

Así que en este caso qué tipo de mapeo tendría? Las respuestas a este ejemplo específico son definitivamente apreciadas, pero también me gustaría tener una idea general de cuándo usar uno-a-muchos y muchos-a-muchos y cuándo usar una tabla de unión versus una columna de unión y unidireccional versus bidireccional.

+4

Parece que todo el mundo responde solo de uno a muchos vs de muchos a muchos. Mira mi respuesta para One-to-many vs Many-to-one. –

Respuesta

103

Uno-a-muchos: una persona tiene muchas habilidades, una habilidad no se reutiliza entre persona (s)

  • unidireccional: una persona puede hacer referencia directamente a las habilidades a través de su Conjunto
  • bidireccional: Cada habilidad "niño" tiene un único puntero de nuevo hasta la persona (que no se muestra en su código)

muchos-a-muchos: una persona tiene muchas habilidades, una habilidad se reutiliza entre persona (s)

  • unidireccional: una persona puede hacer referencia directamente a las habilidades a través de su Conjunto
  • bidireccional: Una habilidad tiene un conjunto de persona (s) que se refieran a la misma.

En una relación uno a varios, un objeto es el "padre" y el otro es el "hijo". El padre controla la existencia del niño.En Many-To-Many, la existencia de cualquier tipo depende de algo que está fuera de ambos (en el contexto de la aplicación más grande).

Su tema (dominio) debe determinar si la relación es Uno a Muchos o Muchos a Muchos, sin embargo, considero que hacer que la relación sea unidireccional o bidireccional es una decisión de ingeniería que intercambia memoria , procesamiento, rendimiento, etc.

Lo que puede ser confuso es que una relación bidireccional Muchos a Muchos no tiene que ser simétrica. Es decir, un grupo de personas podría apuntar a una habilidad, pero la habilidad no necesita relacionarse solo con esas personas. Normalmente lo haría, pero dicha simetría no es un requisito. Toma el amor, por ejemplo, es bidireccional ("I-Love", "Loves-Me"), pero a menudo asimétrico ("¡La amo, pero ella no me ama")!

Todos estos son bien compatibles con Hibernate y JPA. Solo recuerda que a Hibernate u a cualquier otro ORM no le importa mucho mantener la simetría cuando gestiona relaciones bidireccionales de muchos a muchos ... eso depende de la aplicación.

+0

Para aclarar, cualquier relación puede ser unidireccional o bidireccional en su BL o en su asignación de O/R (¡independientemente el uno del otro, incluso!). – apollodude217

+0

El ejemplo de "AMOR" simplemente lo aclaró. ManyToMany es mi tipo de mapeo. –

+0

Super.Esto lo explica muy bien (y en el contexto del ejemplo de OP) – Anupam

6

Tome un vistazo a este artículo: Mapping Object Relationships

Hay dos categorías de relaciones de objeto que tiene que preocuparse de cuando el mapeo. La primera categoría se basa en la multiplicidad y que incluye tres tipos:

*One-to-one relationships. This is a relationship where the maximums of each of its multiplicities is one, an example of which is holds relationship between Employee and Position in Figure 11. An employee holds one and only one position and a position may be held by one employee (some positions go unfilled). 
*One-to-many relationships. Also known as a many-to-one relationship, this occurs when the maximum of one multiplicity is one and the other is greater than one. An example is the works in relationship between Employee and Division. An employee works in one division and any given division has one or more employees working in it. 
*Many-to-many relationships. This is a relationship where the maximum of both multiplicities is greater than one, an example of which is the assigned relationship between Employee and Task. An employee is assigned one or more tasks and each task is assigned to zero or more employees. 

La segunda categoría se basa en direccionalidad y contiene dos tipos, relaciones uni-direccional y relaciones bidireccionales.

*Uni-directional relationships. A uni-directional relationship when an object knows about the object(s) it is related to but the other object(s) do not know of the original object. An example of which is the holds relationship between Employee and Position in Figure 11, indicated by the line with an open arrowhead on it. Employee objects know about the position that they hold, but Position objects do not know which employee holds it (there was no requirement to do so). As you will soon see, uni-directional relationships are easier to implement than bi-directional relationships. 
*Bi-directional relationships. A bi-directional relationship exists when the objects on both end of the relationship know of each other, an example of which is the works in relationship between Employee and Division. Employee objects know what division they work in and Division objects know what employees work in them. 
+2

'esto ocurre cuando el máximo de una multiplicidad es uno y el otro es mayor que uno' lolwut? – serg

1

esto probablemente llamar a una nave de la relación de muchos a muchos de la siguiente manera



public class Person{ 

    private Long personId; 
    @manytomany 

    private Set skills; 
    //Getters and setters 
} 

public class Skill{ 
    private Long skillId; 
    private String skillName; 
    @manyToMany(MappedBy="skills,targetClass="Person") 
    private Set persons; // (people would not be a good convenion) 
    //Getters and setters 
} 

puede que tenga que definir un joinTable + JoinColumn pero lo hará posible también trabajar sin el ...

0

Antes que nada, lea toda la letra pequeña. Tenga en cuenta que NHibernate (así, supongo, Hibernate también) mapeo relacional tiene una correspondencia graciosa con DB y mapeo de gráfico de objetos. Por ejemplo, las relaciones uno-a-uno a menudo se implementan como una relación de muchos a uno.

En segundo lugar, antes de que podamos decirle cómo debe escribir su mapa O/R, también tenemos que ver su DB. En particular, ¿puede una sola Habilidad ser poseída por múltiples personas? Si es así, tienes una relación de muchos a muchos; de lo contrario, es muchos a uno.

En tercer lugar, prefiero no las relaciones muchos-a-muchos directamente, sino modelar la "tabla de unión" en su modelo de dominio - es decir, tratarlo como una entidad, como esto:

class PersonSkill 
{ 
    Person person; 
    Skill skill;  
} 

¿Entonces ves lo que tienes? Tienes dos relaciones uno a muchos. (En este caso, Person puede tener una colección de PersonSkills, pero no tendría una colección de Skills). Sin embargo, algunos preferirán usar la relación muchos a muchos (entre Person y Skill); esto es controversial

cuarto lugar, si usted tiene relaciones bidireccionales (por ejemplo, no sólo la persona tiene un conjunto de habilidades, sino también, Habilidad tiene una colección de Personas), NHibernate hace no hacer cumplir la bidireccionalidad en su BL para usted; solo entiende la bidireccionalidad de las relaciones para fines de persistencia.

En quinto lugar, muchos a uno es mucho más fácil de usar correctamente en NHibernate (y supongo que Hibernate) que de uno a muchos (mapeo de colecciones).

¡Buena suerte!

25

1) Los círculos son entidades/POJO/Beans

2) grados es una abreviatura de grado como en los gráficos (número de bordes)

PK = clave principal, FK = Foreign clave

Tenga en cuenta la contradicción entre el grado y el nombre del lado. Muchos corresponden al grado = 1 mientras que Uno corresponde al grado> 1.

Illustration of one-to-many many-to-one

+42

Puntos de bonificación por impresión artística – Matthew

+0

Me encanta cómo vincula el gráfico de objetos a las tablas en ambas direcciones. –

+0

Mira los nerds, así es como ** PROGRAMMER ** ** HANDWRITING ** se ve así: D –

127

Parece que todo el mundo está respondiendo One-to-many vs Many-to-many:

La diferencia entre One-to-many, Many-to-one y Many-to-Many es:

One-to-many vs Many-to-one es una cuestión de perspectiva. Unidirectional contra Bidirectional no afectará la asignación, pero hará una diferencia sobre cómo puede acceder a sus datos.

  • En el lado One-to-manymany mantendrá referencia del lado one. Un buen ejemplo es "Una persona tiene muchas habilidades". En este caso, Person es el lado y Skill son los muchos lados. Habrá una columna person_id en la tabla skills.

En unidireccional de clasePerson tendrá List<Skill> skills pero Skill no tendrá Person person. En bidireccional se agregan ambas propiedades y le permite acceder a Person con una habilidad (es decir, skill.person).

  • En el lado Many-to-one muchos será nuestro punto de referencia. Por ejemplo, "Un usuario tiene una dirección". En nuestro sistema, muchos usuarios pueden compartir una dirección (por ejemplo, varias personas pueden compartir el mismo número de bloque). En ese caso, la columna address_id en la tabla users será compartida por más de una filas users. En este caso, decimos que users y addresses tienen una relación Many-to-one.

En unidireccional un User tendrá Address address. Bidireccional tendrá un List<User> users adicional en la clase Address.

  • En Many-to-Many miembros de cada parte puede contener referencia a número arbitrario de miembros de la otra parte. Para lograr esto, se usa look up table. Ejemplo de esto es la relación entre médicos y pacientes. Un médico puede tener muchos pacientes y viceversa.
+10

Al menos alguien ... :) – LavaScornedOven

+11

esta debería ser la respuesta aceptada, la mayoría de las otras respuestas se pierden la pregunta. – arg20

+0

El primer ejemplo es incorrecto. Si tiene una persona y una persona tiene @OneToMany con habilidades, esa tabla preson_skills tendría una restricción única en skill_id. Entonces, una habilidad sería asignada solo a una persona. Y no se puede extraer 's.persons', ya que solo' s.person' –