¿Cuál es la diferencia entre las asociaciones unidireccionales y bidireccionales JPA e Hibernate?

¿Cuál es la diferencia entre asociaciones unidireccionales y bidireccionales?

Dado que la tabla generada en el db es la misma, la única diferencia que encontré es que cada lado de las asociaciones bidireccionales tendrá una referencia a la otra, y la no unidireccional.

Esta es una asociación unidireccional

public class User { private int id; private String name; @ManyToOne @JoinColumn( name = "groupId") private Group group; } public class Group { private int id; private String name; } 

La asociación bidireccional

 public class User { private int id; private String name; @ManyToOne @JoinColumn( name = "groupId") private Group group; } public class Group { private int id; private String name; @OneToMany(mappedBy="group") private List users; } 

La diferencia es si el grupo tiene una referencia del usuario.

Entonces me pregunto si esta es la única diferencia? que se recomienda?

La principal diferencia es que la relación bidireccional proporciona acceso de navegación en ambas direcciones, de modo que puede acceder al otro lado sin consultas explícitas. También le permite aplicar opciones en cascada en ambas direcciones.

Tenga en cuenta que el acceso a la navegación no siempre es bueno, especialmente para las relaciones “uno a muchos” y “muchos a muchos”. Imagine un Group que contiene miles de User :

  • ¿Cómo los accederías? Con tantos User s, generalmente necesita aplicar algún tipo de filtrado y / o paginación, por lo que debe ejecutar una consulta de todos modos (a menos que use el filtrado de la colección , que parece un truco para mí). Algunos desarrolladores pueden tender a aplicar filtros en la memoria en tales casos, lo que obviamente no es bueno para el rendimiento. Tenga en cuenta que tener tal relación puede alentar a este tipo de desarrolladores a usarla sin considerar las implicaciones de rendimiento.

  • ¿Cómo agregaría nuevos User al Group ? Afortunadamente, Hibernate mira el lado propietario de la relación cuando la persiste, por lo que solo puede establecer User.group . Sin embargo, si desea mantener la coherencia de los objetos en la memoria, también debe agregar User a Group.users . ¡Pero haría que Hibernate Group.users todos los elementos de Group.users de la base de datos!

Entonces, no puedo estar de acuerdo con la recomendación de las Mejores Prácticas . Debe diseñar relaciones bidireccionales cuidadosamente, teniendo en cuenta los casos de uso (¿necesita acceso de navegación en ambas direcciones?) Y las posibles implicaciones de rendimiento.

Ver también:

  • Disuasión de relaciones “ToMany” en modelos JPA
  • Hibernate asignó problemas de rendimiento de las colecciones

Hay dos diferencias principales.

Accediendo a los lados de la asociación

El primero está relacionado con la forma en que accederá a la relación. Para una asociación unidireccional, puede navegar la asociación solo desde un extremo.

Por lo tanto, para una asociación @ManyToOne unidireccional, significa que solo puede acceder a la relación desde el lado secundario donde reside la clave externa.

Si tiene una asociación @OneToMany unidireccional, significa que solo puede acceder a la relación desde el lado principal donde reside la clave externa.

Para la asociación bidireccional @OneToMany , puede navegar por la asociación en ambos sentidos, ya sea desde el padre o desde el lado del niño.

También necesita usar métodos de utilidad de agregar / eliminar para asociaciones bidireccionales para asegurarse de que ambas partes estén sincronizadas correctamente .

Actuación

El segundo aspecto está relacionado con el rendimiento.

  1. Para @OneToMany , las asociaciones unidireccionales no funcionan tan bien como las bidireccionales .
  2. Para @OneToOne , una asociación bidireccional hará que el padre se busque con entusiasmo si Hibernate no puede decir si se debe asignar el Proxy o un valor nulo .
  3. Para @ManyToMany , el tipo de colección hace una gran diferencia ya que los Sets funcionan mejor que las Lists .

En términos de encoding, una relación bidireccional es más compleja de implementar porque la aplicación es responsable de mantener ambos lados sincronizados de acuerdo con la especificación 5 de JPA (en la página 42). Desafortunadamente, el ejemplo dado en la especificación no proporciona más detalles, por lo que no da una idea del nivel de complejidad.

Cuando no se usa un caché de segundo nivel, generalmente no es un problema no tener los métodos de relación implementados correctamente porque las instancias se descartan al final de la transacción.

Cuando se utiliza la memoria caché de segundo nivel, si algo se corrompe debido a los métodos de manejo de relaciones implementados incorrectamente, esto significa que otras transacciones también verán los elementos dañados (la memoria caché de segundo nivel es global).

Una relación bidireccional correctamente implementada puede simplificar las consultas y el código, pero no debe usarse si no tiene sentido en términos de lógica comercial.

No estoy 100% seguro de que esta es la única diferencia, pero es la diferencia principal . También se recomienda tener asociaciones bidireccionales con los documentos de Hibernate:

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/best-practices.html

Específicamente:

Prefiere las asociaciones bidireccionales: las asociaciones unidireccionales son más difíciles de consultar. En una aplicación grande, casi todas las asociaciones deben ser navegables en ambas direcciones en consultas.

Personalmente, tengo un pequeño problema con esta recomendación general: me parece que hay casos en los que un niño no tiene ningún motivo práctico para conocer a sus padres (por ejemplo, ¿por qué un pedido necesita saber el orden en que se encuentra? asociado con?), pero veo valor en él una parte razonable del tiempo también. Y dado que la bidireccionalidad en realidad no duele nada, no me parece demasiado objetable cumplirla.

    Intereting Posts