tutorial secuencias generatedvalue español java hibernate jpa

java - secuencias - ¿Por qué necesitan entidades separadas en JPA?



jpa tutorial (5)

¡Siempre hay tantas preguntas relacionadas con problemas con entidades separadas!

Primero, a menudo causan LazyInitializationException en Hibernate. Sí, hay otros proveedores de persistencia, que no lanzan excepciones, pero creo que tienen algunos problemas de consistencia. Considere que tenemos entidades A y B que hay una referencia ( @ManyToOne ) de A a B que se requiere que sea no nula.

Comenzamos nuestra sesión, cargamos A instancia y luego cerramos la sesión. Después de eso tratamos de obtener una referencia a B Y supongamos que otra transacción simplemente eliminó nuestras instancias A y B ¡Entonces cuando consultamos desde la base de datos no podemos encontrar la instancia B apropiada y obtenemos un null !

Entonces nuestro contrato es violado. Algún código que se basa en el hecho de que a.getB() devuelve un objeto arrojará una NullPointerException . Con las entidades persistentes esto es imposible porque tenemos toda la carga diferida en la misma transacción con la obtención del objeto mismo, por lo que todas las operaciones son atómicas (si tenemos un aislamiento de transacción adecuado, por supuesto).

También hay problemas cuando quiere almacenar entidades persistentes y separadas en un Set . En ese caso, siempre debes anular equals y hashCode , que generalmente parece incómodo, ya que no puedo ver una forma realmente buena de hacerlo.

Para volver a tener una entidad separada en EntityManager , debe usar merge que es glitchy.

Entonces mi pregunta es: ¿hay un escenario razonable en el que realmente se necesitan entidades separadas? Además, ¿cuándo tiene que mezclar entidades separadas y persistentes y fusionar entidades separadas en un nuevo EntityManager ?


Independiente: una instancia separada es un objeto persistente, pero su sesión se ha cerrado. La referencia al objeto sigue siendo válida, por supuesto, y la instancia separada puede incluso modificarse en este estado. Una instancia separada se puede volver a conectar a una nueva sesión en un momento posterior, lo que hace (y todas las modificaciones) persistentes de nuevo. Esta característica habilita un modelo de programación para unidades de trabajo de larga ejecución que requieren tiempo de reflexión del usuario. Las llamamos transacciones de aplicaciones, es decir, una unidad de trabajo desde el punto de vista del usuario.

Referencias Hibernate DOc

¿Por qué?

La sesión almacena en caché cada objeto que se encuentra en un estado persistente (Hibernate lo observa y verifica para detectar estado sucio). Si lo mantienes abierto durante un tiempo prolongado o simplemente cargas demasiados datos, crecerá infinitamente hasta que obtengas una OutOfMemoryException. Una solución es llamar a clear () y evict () para administrar la caché de la sesión, mantener una sesión abierta durante la sesión de un usuario también significa una mayor probabilidad de datos obsoletos.

Referencias Otra vez Hibernate Doc

Apuesto a que no has leído la documentación de hibernación en sí misma, también tiene escenarios que los explican :)

Explicación simple: con referencia a objetos persistentes ..

Supongamos que un usuario tiene que actualizar un formulario, obtiene los detalles del usuario desde a través de UserObject. Este objeto de usuario es persistente con la sesión. Ahora, si el usuario no envía el formulario, su sesión está abierta hasta que caduque la sesión del servidor, ¿cuánto tiempo esperará? Si ha utilizado getCurrentSession, se recibe otra solicitud de formulario mientras no se envía la anterior, ¡ahora tiene datos sucios! ¿Qué sucede si su objeto está esperando que llegue un dato para un servicio web y tarda lo suficiente? ¿Seguirá teniendo la sesión abierta, objeto persistente con la sesión?


Explicaré por qué ese escenario no debería ocurrir y por qué necesitamos entidades separadas.

Considere que está en una transacción JTA (JPA requiere soporte) y obtenga a . Ahora puede llamar a.getB() ya sea (1) en esta transacción (es decir, se administra la entidad a ) o (2) cuando se desconecta a.

Escenario 1 : ahora, dependiendo del nivel de aislamiento de su transacción, puede ver o no ver qué hacen otras transacciones. Por ejemplo, si tiene el nivel de aislamiento SERIALIZABLE, obtendrá con éxito a.getB() , incluso si esa fila se eliminó en una transacción simultánea. Si esa fila ya fue eliminada y su transacción lo ve, significa que su BD es inconsistente (sin clave externa) o que utilizó el nivel de aislamiento de transacción incorrecto.

Escenario 2 : la entidad a está separada. Cuando se lanza una LazyInitializationException , eso significa que usted llamó a.getB() demasiado tarde para garantizar una consistencia en su aplicación (ya que a no se administra más). Para resolver el problema, simplemente llámalo antes cuando la entidad todavía esté administrada. Un NPE no puede ocurrir.

¿Por qué necesitamos el ESTADO DETALLADO? Bueno, necesitamos un estado en el cual los cambios a una instancia de entidad no sean rastreados. ¿Por qué?

Ejemplo 1 : supongamos que recibe una entidad (con identidad persistente) en la capa EJB y que no hay un estado separado (lo que significa que todas las entidades deben ser administradas). Pero tenemos que hacer una validación antes de persistir en la entidad. Si esa entidad se administrara automáticamente, sus cambios se mantendrían automáticamente en la base de datos. Entonces este nuevo estado fue introducido.

Ejemplo 2 : recibe en la capa EJB una entidad, cualquiera necesita actualizar SOLAMENTE 5 campos de 10 de esa entidad. Si esa entidad entrara automáticamente en el estado administrado, los 10 campos se mantendrían. La solución en este caso es buscar una entidad gestionada y actualizar SOLAMENTE los 5 campos en esa entidad.


Las entidades independientes existen solo para minimizar el tiempo que sus datos están bloqueados debido a una transacción, lo que maximiza la cantidad de usuarios simultáneos. Por supuesto, esto tiene un costo, y usted los enumeró. pero dado que la fusión de conflictos suele ser rara, las personas aceptan algunos errores extraños.

Verá, los conflictos de datos siempre existirán, pero ocurren menos cuando la transacción es corta :-)


Las entidades separadas (ansiosamente captadas) podrían funcionar como DTO en algunos casos. Probablemente no sea algo que deba hacerse en una aplicación empresarial, pero, por ejemplo, un juego de red basado en Java, donde tanto el servidor como el cliente provienen de la misma base de código, el estado del jugador podría ser repretado como entidad y transferido al servidor y persistido allí .

No estoy seguro de que sea una elección mejor que la DTO adecuada, pero técnicamente podría serlo.


Podría ser que una entidad se considere separada porque tiene la misma ID que una entidad en el almacén de persistencia. Imagine que tiene la entidad desde fuera de la aplicación. Podría ser que esta entidad se vea desapegada al tratar de persistir. Ahí tienes que adjuntarlo de nuevo con, de hecho, la fusión.

Realmente no puedo imaginar otras situaciones y tengo curiosidad por las otras respuestas.