programacion mundo hola english curso application and java hibernate jpa java-persistence-api

mundo - java and hibernate



Hibernate no puede obtener simultáneamente múltiples bolsas (11)

Alternativamente, agregue una anotación @Fetch específica de Hibernate a su código:

@OneToMany(mappedBy="parent", fetch=FetchType.EAGER) @Fetch(value = FetchMode.SUBSELECT) private List<Child> childs;

Esto debería solucionar el problema, relacionado con el error Hibernate HHH-1718

Hibernate lanza esta excepción durante la creación de SessionFactory:

org.hibernate.loader.MultipleBagFetchException: no se pueden recuperar varias bolsas simultáneamente

Este es mi caso de prueba:

Parent.java

@Entity public Parent { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; @OneToMany(mappedBy="parent", fetch=FetchType.EAGER) // @IndexColumn(name="INDEX_COL") if I had this the problem solve but I retrieve more children than I have, one child is null. private List<Child> children; }

Niño.java

@Entity public Child { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; @ManyToOne private Parent parent; }

¿Qué tal este problema? ¿Que puedo hacer?

EDITAR

OK, el problema que tengo es que otra entidad "padre" está dentro de mi padre, mi comportamiento real es este:

Parent.java

@Entity public Parent { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; @ManyToOne private AntoherParent anotherParent; @OneToMany(mappedBy="parent", fetch=FetchType.EAGER) private List<Child> children; }

AnotherParent.java

@Entity public AntoherParent { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; @OneToMany(mappedBy="parent", fetch=FetchType.EAGER) private List<AnotherChild> anotherChildren; }

A Hibernate no le gustan dos colecciones con FetchType.EAGER , pero esto parece ser un error, no estoy haciendo cosas inusuales ...

Eliminar FetchType.EAGER de Parent u AnotherParent resuelve el problema, pero lo necesito, por lo que la solución real es usar @LazyCollection(LazyCollectionOption.FALSE) lugar de FetchType (gracias a Bozho por la solución).


Creo que una versión más reciente de hibernate (compatible con JPA 2.0) debería manejar esto. Pero, de lo contrario, puede solucionarlo anotando los campos de la colección con:

@LazyCollection(LazyCollectionOption.FALSE)

Recuerde eliminar el atributo fetchType de la anotación @*ToMany .

Pero tenga en cuenta que en la mayoría de los casos un Set<Child> es más apropiado que List<Child> , así que a menos que realmente necesite un List , vaya a Set


Cuando tiene objetos demasiado complejos con una colección de ahorro no puede ser una buena idea tenerlos todos con EAGER fetchType, use mejor LAZY y cuando realmente necesite cargar las colecciones use: Hibernate.initialize(parent.child) para obtener los datos.


Después de probar con cada una de las opciones descritas en estas publicaciones y en otras, llegué a la conclusión de que la solución es la siguiente.

En cada lugar de XToMany @ XXXToMany(mappedBy="parent", fetch=FetchType.EAGER) e XXXToMany(mappedBy="parent", fetch=FetchType.EAGER) después

@Fetch(value = FetchMode.SUBSELECT)

Esto funciono para mi



La razón por la que obtienes esa excepción es que Hibernate terminaría haciendo un Producto Cartesiano que es malo para el rendimiento.

Ahora, aunque podría "arreglar" el problema utilizando Set lugar de List , no debería hacerlo porque el Producto Cartesiano todavía aparecerá en las declaraciones SQL subyacentes.

Es mejor que cambie de FetchType.EAGER a Fetchype.LAZY ya que la búsqueda ansiosa es una idea terrible que puede llevar a problemas críticos de rendimiento de la aplicación .

Si necesita buscar las entidades secundarias en una jerarquía multinivel, seleccione mejor desde el elemento más interno hasta los padres, como se explica en este artículo .


Para solucionarlo, simplemente tome Set en lugar de List para su objeto anidado.

@OneToMany Set<Your_object> objectList;

y no olvides usar fetch=FetchType.EAGER

funcionará.

Hay un concepto más, CollectionId en Hibernate, si desea quedarse solo con la lista.


Podrías usar una nueva anotación para resolver esto:

@XXXToXXX(targetEntity = XXXX.class, fetch = FetchType.LAZY)

De hecho, el valor predeterminado de fetch es FetchType.LAZY también.


Probamos Establecer en lugar de Lista y es una pesadilla: cuando agregas dos objetos nuevos, equals () y hashCode () fallan en distinguirlos. Porque no tienen ninguna identificación.

Las herramientas típicas como Eclipse generan ese tipo de código a partir de tablas de base de datos:

@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; }

También puede leer este artículo que explica correctamente cómo JPA / Hibernate está desordenado. Después de leer esto, creo que esta es la última vez que uso un ORM en mi vida.

También me he topado con gente de Domain Driven Design que básicamente dice que ORM es una cosa terrible.


Simplemente cambie de tipo de List tipo de Set .


puede mantener las listas de EAGER en el stand en JPA y agregar al menos a una de ellas la anotación JPA @OrderColumn (con el nombre de un campo que debe solicitarse). No hay necesidad de anotaciones específicas de hibernación. Pero tenga en cuenta que podría crear elementos vacíos en la lista si el campo elegido no tiene valores a partir de 0

[...] @OneToMany(mappedBy="parent", fetch=FetchType.EAGER) @OrderColumn(name="orderIndex") private List<Child> children; [...]

en Niños entonces debes agregar el campo orderIndex