occurred - hibernate: LazyInitializationException: no se pudo inicializar el proxy
hibernate initialize exception (14)
Bien, finalmente descubrí dónde fui negligente. Estaba bajo la noción errónea de que debería ajustar cada método DAO en una transacción. ¡Terriblemente equivocado! Aprendí mi lección He arrastrado todo el código de transacción de todos los métodos DAO y he configurado las transacciones estrictamente en la capa de aplicación / administrador. Esto ha resuelto por completo todos mis problemas. Los datos se cargan de manera floja cuando los necesito, se cierran y se cierran una vez que realizo la confirmación.
La vida está bien ... :)
Aquí hay uno que me tiene perplejo. Estoy tratando de implementar una estructura básica Hibernate DAO, pero estoy teniendo un problema.
Aquí está el código esencial:
int startingCount = sfdao.count();
sfdao.create( sf );
SecurityFiling sf2 = sfdao.read( sf.getId() );
sfdao.delete( sf );
int endingCount = sfdao.count();
assertTrue( startingCount == endingCount );
assertTrue( sf.getId().longValue() == sf2.getId().longValue() );
assertTrue( sf.getSfSubmissionType().equals( sf2.getSfSubmissionType() ) );
assertTrue( sf.getSfTransactionNumber().equals( sf2.getSfTransactionNumber() ) );
Falla en la tercera assertTrue donde intenta comparar un valor en sf con el valor correspondiente en sf2. Aquí está la excepción:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:86)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:140)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at com.freightgate.domain.SecurityFiling_$$_javassist_7.getSfSubmissionType(SecurityFiling_$$_javassist_7.java)
at com.freightgate.dao.SecurityFilingTest.test(SecurityFilingTest.java:73)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:40)
Creo que Piko quiere decir en su respuesta que existe el archivo hbm. Tengo un archivo llamado Tax.java. La información de mapeo se guarda en el archivo hbm (= hibernate mapping). En la etiqueta de clase hay una propiedad llamada flojo . Establezca esa propiedad en verdadero. El siguiente ejemplo de hbm muestra una forma de establecer la propiedad floja en falso .
`id ... ''
Si está utilizando Anotaciones, busque en la documentación de hibernación. http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/
Espero que haya ayudado.
De forma predeterminada, todas las asociaciones one-to-many
y many-to-many
obtienen de forma lenta al acceder por primera vez.
En su caso de uso, podría superar este problema al incluir todas las operaciones de DAO en una transacción lógica:
transactionTemplate.execute(new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus transactionStatus) {
int startingCount = sfdao.count();
sfdao.create( sf );
SecurityFiling sf2 = sfdao.read( sf.getId() );
sfdao.delete( sf );
int endingCount = sfdao.count();
assertTrue( startingCount == endingCount );
assertTrue( sf.getId().longValue() == sf2.getId().longValue() );
assertTrue( sf.getSfSubmissionType().equals( sf2.getSfSubmissionType() ) );
assertTrue( sf.getSfTransactionNumber().equals( sf2.getSfTransactionNumber() ) );
return null;
}
});
Otra opción es buscar todas las asociaciones PEREZAS al cargar su entidad, de modo que:
SecurityFiling sf2 = sfdao.read( sf.getId() );
también debería buscar el tipo de submissionType
LAZY:
select sf
from SecurityFiling sf
left join fetch.sf.submissionType
De esta manera, busca con ansias todas las propiedades perezosas y puede acceder a ellas después de que la sesión también se cierre.
Puede buscar tantas asociaciones [one|many]-to-one
y "[una | muchas] a muchas" asociaciones de listas (debido a la ejecución de un producto cartesiano).
Para inicializar múltiples "[uno | many] -to-many", debe usar Hibernate.initialize(collection) , justo después de cargar su entidad raíz.
El problema es que está intentando acceder a una colección en un objeto que está detached . Debe volver a adjuntar el objeto antes de acceder a la colección en la sesión actual. Puedes hacerlo a través de
session.update(object);
Usar lazy=false
no es una buena solución porque está descartando la función Inicialización lazy=false
de Hibernate. Cuando lazy=false
, la colección se carga en la memoria al mismo tiempo que se solicita el objeto. Esto significa que si tenemos una colección con 1000 elementos, todos se cargarán en la memoria, a pesar de que vamos a acceder a ellos o no. Y esto no es bueno
Lea este article donde se explica el problema, las posibles soluciones y por qué se implementa de esta manera. Además, para comprender Sesiones y Transacciones, debe leer este otro artículo .
Esto generalmente significa que la sesión propietaria de Hibernate ya se ha cerrado. Puede hacer uno de los siguientes para solucionarlo:
- Cualquiera que sea el objeto que crea este problema, use
HibernateTemplate.initialize(object name)
- Use
lazy=false
en sus archivos hbm.
Parece que solo tu DAO está usando sesión. Por lo tanto, se abre una nueva sesión y luego se cierra para cada llamada a un método DAO. Por lo tanto, la ejecución del programa se puede reanudar como sigue:
// open a session, get the number of entity and close the session
int startingCount = sfdao.count();
// open a session, create a new entity and close the session
sfdao.create( sf );
// open a session, read an entity and close the session
SecurityFiling sf2 = sfdao.read( sf.getId() );
// open a session, delete an entity and close the session
sfdao.delete( sf );
etc...
Por defecto, la recopilación y la asociación en una entidad son flojas: se cargan desde la base de datos a petición. Así:
sf.getSfSubmissionType().equals( sf2.getSfSubmissionType() )
lanza una excepción porque solicita una nueva carga desde la base de datos, y la sesión asociada con la carga de la entidad ya se ha cerrado.
Hay dos enfoques para resolver este problema:
crea una sesión para incluir todo nuestro código. Por lo tanto, significaría cambiar su contenido DAO para evitar abrir una segunda sesión
crea una sesión y luego actualiza (es decir, vuelve a conectar) tu entidad a esta sesión antes de las aserciones.
session.update (object);
Si conoce el impacto de lazy=false
y aún lo desea, lo hace de manera predeterminada (por ejemplo, para prototipos), puede usar cualquiera de los siguientes:
- si está utilizando la configuración XML: agregue
default-lazy="false"
a su elemento<hibernate-mapping>
- si está utilizando la configuración de anotación: agregue
@Proxy(lazy=false)
a su (s) clase (s) de entidad
Si está gestionando la sesión de Hibernate de forma manual, le recomendamos que consulte sessionFactory.getCurrentSession () y los documentos asociados aquí:
http://www.hibernate.org/hib_docs/v3/reference/en/html/architecture-current-session.html
Si está utilizando Hibernate con anotaciones JPA, esto será útil. En su clase de servicio, debe haber un definidor para el administrador de entidades con @PersistenceContext. cambie esto a @PersistenceContext (type = PersistenceContextType.EXTENDED). Entonces puede acceder a la propiedad de pereza en cualquier lugar.
Si está utilizando la carga lenta, su método debe ser anotado con
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
para la sesión sin estado EJB
Si usa la anotación Spring y JPA, la forma más sencilla de evitar el problema con la sesión en la inicialización perezosa es replaysing:
@PersistenceContext
a
@PersistenceContext(type = PersistenceContextType.EXTENDED)
También encontramos este error. Lo que hicimos para resolver el problema es que agregamos un lazy = false en el archivo de mapeo de Hibernate.
Parece que tuvimos una clase A que está dentro de una sesión que carga otra clase B. Estamos intentando acceder a los datos en la clase B, pero esta clase B está separada de la sesión.
Para que podamos acceder a esta Clase B, tuvimos que especificar en el archivo de mapeo Hibernate de la clase A el atributo lazy = false. Por ejemplo,
<many-to-one name="classA"
class="classB"
lazy="false">
<column name="classb_id"
sql-type="bigint(10)"
not-null="true"/>
</many-to-one>
Ver mi artículo Tuve el mismo problema, LazyInitializationException, y esta es la respuesta que finalmente se me ocurrió:
http://community.jboss.org/wiki/LazyInitializationExceptionovercome
Establecer lazy = false no es la respuesta; puede cargar todo de una vez, y eso no es necesariamente bueno. Ejemplo:
1 tabla de registros A referencias:
5 registros de la tabla B referencias:
25 registros de la tabla C referencias:
125 registros tabla D
...
etc. Este es solo un ejemplo de lo que puede salir mal.
--Tim Sabin
use Hibernate.initialize para campo perezoso