java - significa - ¿Cuál es la diferencia entre las asociaciones unidireccionales y bidireccionales JPA e Hibernate?
relaciones bidireccionales hibernate (4)
En términos de codificación, 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.
¿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<User> users;
}
La diferencia es si el grupo tiene una referencia del usuario.
Entonces me pregunto si esta es la única diferencia? que se recomienda?
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.
- Para
@OneToMany
, las asociaciones unidireccionales no funcionan tan bien como las bidireccionales . - 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 . - Para
@ManyToMany
, el tipo de colección hace una gran diferencia ya que losSets
funcionan mejor que lasLists
.
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
alGroup
? Afortunadamente, Hibernate mira el lado propietario de la relación cuando la persiste, por lo que solo puede establecerUser.group
. Sin embargo, si desea mantener la coherencia de los objetos en la memoria, también debe agregarUser
aGroup.users
. ¡Pero haría que HibernateGroup.users
todos los elementos deGroup.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:
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.