Quiero ejecutar varias instrucciones de actualización en la misma consulta en modo de hibernación Hql.
como a continuación:
hql = " update Table1 set prob1=null where id=:id1; "
+ " delete from Table2 where id =:id2 ";
...
query.executeUpdate();
en el mismo executeUpdate
llamada que desea actualizar los registros de la Tabla1 y eliminar registros de la Tabla2.
Es posible?
si la relación entre las tablas y los datos que desea modificar permitir esta declaración, sí es posible, pero en mi humilde opinión, usted debe usar el modo de Hibernación
Puedo ejecutar la instrucción en SQL estándar. Pero hibernate lanza la excepción
necesitarás varios
Como he dicho en mi respuesta, esto no es posible con HQL, debido a que Hibernate utiliza
A continuación, la respuesta es simplemente No. Si usted va a realizar múltiples actualización masiva como esta, hacerlo bajo Hibernate rara vez es una buena elección. ¿Por qué no hacerlo a través de JDBC puro, entonces? Y, si usted está haciendo la actualización masiva como esta, DB (ida y vuelta rara vez es el cuello de botella (a menos que usted está haciendo actualizar/eliminar por entidad, por lo que se deberá hacer por cambiar el estado de entidad/sesión.delete(), y dejar de Hibernación problema de detectar los cambios y el tema de la SQLs en lotes)
Criteria
en lugar de hql
idioma. stackoverflow.com/questions/197474/…Puedo ejecutar la instrucción en SQL estándar. Pero hibernate lanza la excepción
unexpected char: ';'
. Hibernate no es capaz de analizar la cadena correctamente. Me pregunto si hay otra sintaxis para la declaración o de otra manera utilizar HQL.necesitarás varios
Query::executeUpdate
, no puede concatenar, pero será la misma transacción en la sesiónComo he dicho en mi respuesta, esto no es posible con HQL, debido a que Hibernate utiliza
PreparedStatement
s para este.A continuación, la respuesta es simplemente No. Si usted va a realizar múltiples actualización masiva como esta, hacerlo bajo Hibernate rara vez es una buena elección. ¿Por qué no hacerlo a través de JDBC puro, entonces? Y, si usted está haciendo la actualización masiva como esta, DB (ida y vuelta rara vez es el cuello de botella (a menos que usted está haciendo actualizar/eliminar por entidad, por lo que se deberá hacer por cambiar el estado de entidad/sesión.delete(), y dejar de Hibernación problema de detectar los cambios y el tema de la SQLs en lotes)
OriginalEl autor Nebras | 2016-08-19
En definitiva, lo que están buscando es algo así como el procesamiento por lotes en JDBC. Thich no es de Hibernate para la Actualización Masiva de consulta, y dudo si es que alguna vez será considerado para la Hibernación.
De mi experiencia en el pasado, los Lotes cuentan para HQL rara vez es útil en la vida real. Puede sonar extraño que algo sea útil en SQL+JDBC, pero no en HQL. Voy a tratar de explicar.
Por lo general, cuando trabajamos con Hibernate (u otro similar ORM), trabajamos en contra de las entidades. Hibernate será el encargado de sincronizar nuestros entidades del estado con DB, que es la mayoría de los casos que JDBC procesamiento por lotes puede ayudar a mejorar el rendimiento. Sin embargo, en modo de Hibernación no cambiamos individuales de la entidad estatal por mayor consulta de Actualización.
Simplemente dar un ejemplo, en pseudo-código:
En JDBC, puede hacer algo como (estoy tratando de imitar lo que se muestra en el ejemplo):
Ingenuo traducción de JDBC lógica de Hibernación puede dar algo como esto:
Sospecho que usted piensa que necesita el procesamiento por lotes característica porque estás haciendo algo similar (en base a su ejemplo, que el uso de actualización masiva para el registro individual). Sin embargo es NO cómo esto debe ser hecho en Hibernate/JPA
(En realidad es mejor para envolver la persistencia de la capa de acceso a través de un repositorio, aquí estoy sólo la simplificación de la imagen)
Al hacerlo, Hibernate es lo suficientemente inteligente como para detectar modificado/eliminado/inserta entidades, y hacer uso de JDBC lote para hacer la base de datos de la COALICIÓN de operaciones en
flush()
. Más importante, este es el propósito para el ORM: queremos proporcionar comportamiento ricos en las entidades de trabajo, por lo cual el estado interno de cambio de las entidades pueden ser «transparente» que se reflejan en el almacenamiento persistente.HQL Actualización Masiva objetivos para otro uso, que es algo así como una actualización masiva a DB a afectar a una gran cantidad de registros, por ejemplo:
Rara vez hay una necesidad de la ejecución de una gran cantidad de consultas en este tipo de escenario de uso, por tanto, la sobrecarga de DB de ida es insignificante, y por lo tanto, el beneficio y el procesamiento por lotes de apoyo para la actualización masiva de consulta rara vez es significativo.
No puedo omitir que hay casos en que usted realmente necesita para emitir una gran cantidad de consultas de actualización que no es apropiado para ser realizadas por la entidad comportamiento. En tal caso, usted puede desear reconsiderar si la Hibernación es el instrumento adecuado para ser utilizado. Usted puede considerar el uso de JDBC puro en tal caso de uso, de modo que usted tiene control sobre cómo se ejecutan consultas.
OriginalEl autor Adrian Shum
executeUpdate()
ejecuta una sola consulta de actualización.Así que, no, usted no puede hacerlo. Usted tiene que ejecutar como muchas de las consultas de actualización de las tablas de actualizar/eliminar.
Además, tiene un código más limpio si consultas por separado :
executeUpdate()
No significa que las consultas deben obligatorio ser trasmitida uno por uno.
El Procesamiento por lotes es una característica de Hibernate para mejorar el rendimiento cuando se desea ejecutar múltiples consultas. Tienes que habilitar la característica de utilizar.
hibernate.jdbc.batch_size
propiedad debe ser configurado con un valor adecuado.Además de la documentación oficial :
Sin embargo, en su caso, será inútil porque como Dragan Bozanovic explicó actualizar/eliminar tablas diferentes en sus consultas. Así, se podría crear como muchos de los lotes de las ejecuciones como tablas consultados.
Así que, usted debe ejecutar cada consulta individual. Sólo commit() la transacción cuando se considere que debe ser :
OriginalEl autor davidxxx
No, no es posible, debido a que Hibernate utiliza
PreparedStatement
s de esto (lo cual es bueno porque de bind variables), yPreparedStatement
s no admite lotes que consta de múltiples declaraciones diferentes.PreparedStatement
sólo puede lotes de diferentes combinaciones de las variables vinculadas por una declaración, en la que Hibernate utiliza para lote de inserciones y actualizaciones al purgar los cambios en el contexto de persistencia (sesión).OriginalEl autor Dragan Bozanovic
El SQL generado por JPA granel actualizaciones o eliminaciones, es decir, las llamadas a javax.la persistencia.Consulta.executeUpdate() no pueden ser procesadas por lotes por Hibernate cuando pasa a través de JDBC. @DraganBozanovic y @AdrianShum ya hemos explicado esto, pero para añadir a sus comentarios: executeUpdate() devuelve un entero (int, el número de entidades actualizado o eliminado) – independientemente de lavado de la sesión de Hibernate, ¿cómo podría el int ser devueltos sin llamar a la base de datos inmediatamente y de forma sincrónica? El JPQL/HQL/SQL tendría que ser evaluado en el lado del cliente, lo cual no es posible debido a las entidades a ser masiva, actualiza, elimina puede que ni siquiera se han leído en la sesión de Hibernate. Además si el update o delete no fueron ejecutados en la base de datos de inmediato, las consultas posteriores a leer en entidades JPA podría obtener datos obsoletos. Ejemplo:
Si el executeUpdate en 1 permitió ser aplazado hasta después de la lectura de a 2, luego de obtener la respuesta incorrecta (el Cliente todavía existe).
Usted necesita leer las entidades en el uso de JPA, actualización de ellos, y dejar de Hibernación generar la actualización de SQL (que se puede batch), o llame a JDBC directamente para realizar las actualizaciones por lotes.
OriginalEl autor coder
¿Por qué no ejecutar las dos consultas por separado en una Transaccional método
Al anotar el método con @Transactional, si la consulta falla, el otro no se ejecutará.
Yo ya uso un AOP en un alto nivel de llamada de servicio para la gestión de transacciones.
OriginalEl autor Olakunle Awotunbo