1. Consulta de objetos de entidad
La consulta de objetos de entidad es la base de la consulta HQL. Como lenguaje de consulta de objetos, es diferente de SQL durante las operaciones de consulta. El contenido en la cadena de consulta debe reemplazarse por el nombre de clase y el nombre del atributo de clase. Este método de consulta es relativamente simple. Mientras tenga habilidades SQL, es muy simple usar HQL. Sin embargo, hay algunos problemas a los que deben prestarse atención, es decir, consultar y obtener datos no es el propósito, y lo que debe considerarse es cómo escribir declaraciones de consulta eficientes, que es el foco de la discusión.
1.N+1 problema
(1) ¿Cuál es el problema N+1?
Cuando escuché por primera vez este sustantivo, puedo tener dudas. Nunca antes había oído hablar del problema N+1. Entonces, ¿qué significa? N+1 se refiere a n datos en una tabla, por lo que al obtener estos n datos, se generará el comando n+1 sql. Esta operación se llama N+1. Aquí, 1 se refiere a emitir una declaración que busca la lista de identificación, y N se refiere a la emisión de declaraciones N SQL basadas en ID para cargar objetos relacionados. Este tipo de operación de consulta es muy ineficiente y a menudo se genera en los iteradores. Es decir, si convertimos directamente los resultados de la consulta en iteradores, este problema ocurrirá, de la siguiente manera:
public void testQuery () {session session = null; intente {session = hibernateUtils.getSession (); session.BeginTransaction (); /*** Habrá un problema N+1. El llamado N+1 Worth es emitir declaraciones SQL N+1** 1: Problema una declaración que consulte la lista de identificación** n: Problema n declaraciones SQL basadas en la identificación y cargue el objeto correspondiente*/ iterator iterator = session.createQuery ("del estudiante"). Iterate (); while (iter.hasnext ()) {estudiante estudiante = (estudiante) iter.next (); System.out.println (student.getName ()); } session.getTransaction (). Commit (); } catch (Exception e) {E.PrintStackTrace (); session.getTransaction (). Rollback (); } finalmente {hibernateUtils.clossessession (sesión); }}El código de consulta anterior causará el problema N+1, porque la consulta se devuelve como iterador, de modo que se emitirá una declaración SQL si no se genera una vez. Esto depende principalmente del mecanismo de consulta del iterador, que consulte los datos del caché. Si los datos no existen en el caché, los datos se convertirán primero en la memoria, por lo que se emitirá una declaración de consulta SQL en este momento, por lo que se generará una declaración SQL cada iteración. Este método de escritura es en realidad un error y se puede resolver utilizando otros métodos para optimizar.
(2) Evite el problema N+1
El problema de N+1 ocurre debido al uso inadecuado de iterado. Por supuesto, se pueden usar otros métodos para evitar este problema de N+1. Aquí hay un método de lista. La mayor diferencia entre List e ITerate es que la lista pone datos en el caché, pero no usa el caché. Por defecto, la lista emitirá declaraciones SQL cada vez. Antes de usar iterate, puede usar la lista para guardar los datos en la base de datos, de modo que iterate pueda leer desde el caché al acceder a los datos, evitando la ocurrencia de problemas n+1. El código es el siguiente:
public void testQuery () {session session = null; intente {session = hibernateUtils.getSession (); session.BeginTransaction (); Lista de estudiantes = session.createQuery ("del estudiante"). List (); System.out.println ("----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- Entonces no se emiten una consulta de declaraciones SQL basada en ID, y los datos en la memoria caché se usan directamente * * iterer Método Si los datos existe en la memoria caché, puede mejorar el rendimiento, de lo contrario se producirán los problemas n+1 */ // puede usar el alias iterador = session.createquery ("del estudiante"). Iterer (); System.out.println (Student.getName ()); }}El ejemplo anterior evita el problema N+1, porque después de realizar la operación de la lista, los datos se colocarán en el caché de la sesión (caché de primer nivel). Por lo tanto, cuando se use iterate, se emitirá una declaración para consultar la lista de identificación, y luego los datos correspondientes se cargarán en el caché de acuerdo con la ID. Si hay datos que lo coinciden en el caché, la consulta de la instrucción SQL basada en la ID ya no se emitirá, y los datos en el caché se utilizarán directamente. El método de Iterer puede mejorar el rendimiento si existe datos en el caché, de lo contrario se producirán problemas n+1.
2. Consulta de navegación de objetos
La navegación del objeto se refiere a obtener datos de otro objeto de acuerdo con la navegación de atributos del objeto en un objeto. Esto puede simplificar las declaraciones de consulta y optimizar los métodos de consulta. Si seguimos nuestras ideas habituales, podemos reescribir y escribir un objeto de otra clase para obtener la operación de otro objeto, que es más engorroso para comparar la declaración de navegación de objetos.
@SupessWarnings ({"sin verificar", "RawTypes"}) public void testQuery1 () {session session = null; intente {session = hibernateUtils.getSession (); session.BeginTransaction (); // Devuelve la lista de atributos de conjunto de resultados, el tipo de elemento y los tipos de atributos en la clase de entidad son los mismos estudiantes de lista = session.createQuery ("de los estudiantes donde s.classes.name como '%2%'"). List (); para (iterator item = students.iterator (); ite.hasnext ();) {estudiante obj = (estudiante) ite.next (); System.out.println (obj.getName ()); } session.getTransaction (). Commit (); } catch (Exception e) {E.PrintStackTrace (); session.getTransaction (). Rollback (); } finalmente {hibernateUtils.clossessession (sesión); }}La declaración de consulta en el ejemplo anterior utiliza el método de navegación de objetos. La declaración de consulta es la consulta de información del objeto del alumno, pero los atributos del objeto a comparar provienen del atributo de nombre del objeto de clases. En este momento, el uso del método de consulta de navegación de objetos mejorará significativamente la eficiencia de la consulta y optimizará la declaración de consulta. Si fuera un método de consulta ordinario, se puede generar una gran cantidad de declaraciones de conexión, lo cual es muy complicado.
2. Consulta nativa de SQL
El valor de la consulta nativa es utilizar las declaraciones SQL para consultar y obtener datos, en lugar de usar declaraciones HQL. Su método de uso es en realidad muy simple, similar a HQL. Solo necesita usar el método CreateSQLQuery para consultar. En realidad, es similar al método CreateQuery de HQL. El código es el siguiente:
public void testQeury () {session session = null; intente {session = hibernateUtils.getSession (); session.BeginTransaction (); List list = session.CreateSQLQuery ("Seleccionar * de t_student"). List (); for (iterator item = list.iterator (); ite.hasnext ();) {object [] obj = (object []) ite.next (); System.out.println (obj [0]+","+obj [1]); } session.getTransaction (). Commit (); } catch (Exception e) {E.PrintStackTrace (); session.getTransaction (). Rollback (); } finalmente {hibernateUtils.clossessession (sesión); }}El código anterior utiliza el método CreateSQLQuery. La cadena de consulta en el método es una declaración SQL. Implementa el método de consulta de cadena subyacente. La diferencia es que HQL tiene otra capa de embalaje, y configura las opciones de dialecto correspondientes en Hibernate.cfg.xml para completar la asignación.
3. Consulta de conexión
Las consultas de conexión a menudo se usan en SQL para obtener una colección de múltiples objetos. Entre ellos, los más utilizados son la unión interna, la unión izquierda, la unión derecha, etc., que se refieren a la consulta de unión interna, la consulta de unión externa izquierda y la consulta de unión externa derecha. El contenido que devuelven durante la consulta es el producto cartesiano entre entidades, el contenido de la consulta y algún contenido de la tabla izquierda, el contenido de la consulta y algún contenido de la tabla correcta, y la función de consulta es poderosa. El método de consulta de conexión de HQL y la consulta de conexión de SQL son los mismos en los resultados de la consulta, pero existen ligeras diferencias en las declaraciones de consulta.
1. Conexión interna
La consulta intraJuda de HQL se puede consultar utilizando la declaración de unión interna o la declaración de unión, y el conjunto de resultados obtenido es un producto cartesiano. Similar a la consulta intra-conexión SQL, la consulta de unión de HQL se divide en dos tipos: explícito e implícito. La consulta mostrada se refiere a la palabra clave de unión en la cadena de consulta. La consulta implícita no necesita agregar unirse en la cadena.
// conexiones interiores @SupplesWarnings ({"sin verificar", "RawTypes"}) public void testQuery () {session session = null; intente {session = hibernateUtils.getSession (); session.BeginTransaction (); // Devuelve la lista de atributos del conjunto de resultados, el tipo de elemento y los tipos de atributos en la clase de entidad son los mismos estudiantes de la lista = session.createQuery ("Seleccione s.name, c.name from Student s se une s.classes c"). List (); for (iterator item = students.iterator (); ite.hasnext ();) {objeto [] obj = (objeto []) ite.next (); System.out.println (obj [0]); } session.getTransaction (). Commit (); } catch (Exception e) {E.PrintStackTrace (); session.getTransaction (). Rollback (); } finalmente {hibernateUtils.clossessession (sesión); }}
2. Conexión externa
Las conexiones externas se dividen en la conexión exterior izquierda y la consulta de conexión exterior derecha. Los métodos de consulta son similares, pero el resultado de la consulta es diferente. Son las mismas que la conexión externa de SQL en los resultados de la consulta. La diferencia es el método de escritura. El código específico es el siguiente:
@SupessWarnings ({"sin verificar", "RawTypes"}) public void testQuery () {session session = null; intente {session = hibernateUtils.getSession (); session.BeginTransaction (); // Devuelve la lista de atributos de conjunto de resultados, el tipo de elemento y los tipos de atributos en la clase de entidad son los mismos estudiantes de la lista = session.createQuery ("Seleccione s.name, c.Name de Student S Left S.Classes C"). LIST (); for (iterator item = students.iterator (); ite.hasnext ();) {objeto [] obj = (objeto []) ite.next (); System.out.println (obj [0]); } session.getTransaction (). Commit (); } catch (Exception e) {E.PrintStackTrace (); session.getTransaction (). Rollback (); } finalmente {hibernateUtils.clossessession (sesión); }}El código anterior utiliza una instrucción de consulta de unión externa izquierda. El método de consulta de unión externa derecha correspondiente es similar a la unión externa izquierda. Simplemente convierta de izquierda a derecha. Los datos de consulta se guardan en el objeto de lista, y el contenido de consulta se puede obtener a través de la lista.
4. Consulta de nombres externos
Consulta con nombres externos se refiere a escribir declaraciones de consulta en un archivo de mapeo y usar la etiqueta <Sartery> para definir las declaraciones HQL en el archivo de asignación. De esta manera, las declaraciones HQL definidas pueden realizar la función de configuración de la función. Si hay un problema, solo necesita modificar la configuración. Si desea utilizar esta instrucción SQL, puede usar el método session.getNamedQuery () en el programa para obtener la cadena de consulta HQL, como se muestra en el siguiente ejemplo.
1. Declaración de consulta externa
El siguiente ejemplo demuestra la aplicación de declaraciones de consulta externas, agregue la etiqueta <SCERY> al archivo de asignación, agregue el atributo de nombre a la etiqueta y agregue la cadena a <! [CDATA []]>, de modo que la cadena de consulta correspondiente se pueda obtener en el programa de acuerdo con el atributo de nombre de la consulta.
<? xml versión = "1.0"?> < table="t_student"> <id name="id"> <generator//id> <property name="name"/> <property name="createTime"></property> <!-- Add a new Classes column to the Student on one side, and the column name should be the same as the List of Classes.hbm.xml --> <many-to-one name="classes" column="classesid"></many-to-one> </class> <query name = "QueryStudent"> <! [CDATA [Seleccione S de Student S donde S.ID <? ]]> </Query> </Hibernate Mapping>
La consulta externa con nombre coloca la instrucción de consulta en el archivo de mapeo, por lo que puede considerarse una cadena de consulta pública. Esta es su ventaja, para que se puedan obtener y utilizar otros archivos de programa. Además, aumenta la conveniencia de la modificación como una cadena pública.
2. Aplicación del programa
Después de definir las declaraciones de consulta externas, es necesario usarlas en el programa. HQL proporciona el método GetNameQuery para obtener la cadena de instrucción de consulta externa. Se debe agregar un nombre de cursor externo a este método. HQL consultará el bloque de instrucción SQL correspondiente basado en el nombre del cursor, de la siguiente manera:
// consulta de nombres externos @SupplesSwarnings ({"sin verificar", "RawTypes"}) public void testQuery () {session session = null; intente {session = hibernateUtils.getSession (); session.BeginTransaction (); Lista de estudiantes = session.getNamedQuery ("QueryStudent"). SetParameter (0, 10) .List (); para (iterator item = students.ite.hasnext ();) {estudiante obj = (estudiante) ite.next (); System.out.println (obj.getName ()); } session.getTransaction (). Commit (); } catch (Exception e) {E.PrintStackTrace (); session.getTransaction (). Rollback (); } finalmente {hibernateUtils.clossessession (sesión); }}