La última vez que aprendimos a usar criterios para realizar operaciones relacionadas juntos, pero dado que los criterios no son el método de consulta recomendado oficialmente por Hibernate, no lo usamos mucho. Ahora echemos un vistazo al HQL recomendado oficialmente y aprendamos cuán poderoso es juntos.
¿Cuál es la diferencia entre HQL o Declaración de consultas Hibernate y SQL? La diferencia entre una letra, jaja.
Por supuesto, este no es el caso. La diferencia entre HQL y SQL se encuentra en las diferentes ideas. HQL utiliza una dirección orientada a objetos para consultar, mientras que SQL usa una consulta para tablas de base de datos bidimensionales. Lo que se incluye aquí es la diferencia en las ideas. HQL es en realidad SQL, y Hibernate lo hace para convertir y generar SQL internamente.
1) Sin más preámbulos, echemos un vistazo a su poder.
del usuario
Este código es muy familiar, porque a menudo usamos a partir de nombres de tabla en SQL, pero la diferencia aquí es que el usuario no es el nombre de la tabla aquí, sino el nombre de la clase de entidad, y Hibernate nos ayuda a mapear.
Declaraciones SQL asociadas, si queremos encontrar un cierto atributo y limitarlo condicionalmente de acuerdo con cierto atributo, podemos obtener una declaración similar:
Seleccione USR.NAME, USR.AGE del usuario donde USR.AGE> 20 y USR.AGE <60
De esta manera, encontramos los nombres y edades de usuarios mayores de 20 años o menos de 60 años. Es fácil de entender.
El y, o, como, <,>, = y así sucesivamente en las declaraciones SQL se pueden usar en HQL.
Cabe señalar que cuando consultamos múltiples atributos, el resultado devuelto es una matriz de objeto [], y cuando solo uno, se devuelve el objeto. Esto requiere diferentes métodos de análisis, por lo que debe prestarle atención al consultar.
2) Por supuesto, dijimos anteriormente que HQL está orientado a objetos, y si hacemos esto, no es una idea orientada a objetos. Vamos a cambiarlo:
Seleccione nuevo usuario (usr.name, usr.age) del usuario usr donde usr.age> 20De esta manera, colocamos el resultado de la consulta en el objeto de usuario. Tenga en cuenta que el constructor del usuario se llama aquí. Debe haber un constructor de usuarios que reciba dos parámetros en la clase de usuario, de lo contrario se informará un error. El mensaje de error es más o menos como sigue:
No se puede localizar el constructor apropiado en la clase [org.hibernate.tutorial.domain8.user]
No puede encontrar un constructor adecuado. Está muy claro que solo agregue el constructor que recibe los parámetros correspondientes.
Tenga en cuenta que cuando verificamos la ID correspondiente, no lo descubrimos. Si llamamos al método SaveRupdate en este momento, realmente realizó la operación guardada.
Echemos un vistazo al código de prueba:
Después de ejecutar la declaración de consulta anterior, realizo las siguientes operaciones:
while (iter.hasnext ()) {user user = (user) iter.next (); user.setName ("Sun2"); session.SaveOrupdate (usuario); } En este momento, la declaración hibernada es:
Hibernate: inserte en valores de usuario (user_name, edad) (?,?)
Inserta uno nuevo, no una actualización.
Entonces, si lo necesitamos para actualizar, necesitamos averiguar la identificación juntos:
Seleccione nuevo usuario (USR.Name, USR.AGE, USR.ID) del usuario USR donde usr.age> (seleccione AVG (USR.AGE) desde USR)
Recuerde modificar el constructor del usuario.
En este momento, ejecutamos nuestro código de prueba nuevamente y obtendrá:
Hibernate: actualizar user set user_name =?, Edad =? ¿Dónde user_id =?
Seleccione USR.Name del usuario USR donde USR.AGE> (seleccione AVG (USR.AGE) desde USR)
Este HQL detecta el nombre del usuario que es mayor que la edad promedio.
4) En Hibernate 3, podemos actualizar y eliminar fácilmente objetos, sin tener que cargar primero y luego eliminar en 2. Podemos hacerlo directamente en una declaración:
Actualizar el nombre del usuario nombre = '123123' donde nombre = 'Sun33'
Las declaraciones de eliminación son similares:
Eliminar usuario donde nombre = '123123'
5) También es fácil agrupar y ordenar en Hibernate. Simplemente use el grupo y ordene, y no hablaré más sobre eso en este momento.
6) Vemos que lo anterior se escribe directamente para consultar o actualizar. Si necesitamos una asignación dinámica, o hay demasiadas tareas, no podemos empalmar cadenas como JDBC. Se estima que hay más de 5, y todos en el equipo del proyecto quieren regañarme, jaja.
Es mejor usar un método moderno, usar marcadores de posición y luego establecer valores específicos.
Nuestro código directo:
Query Query = Session.CreateQuery ("Seleccione nuevo usuario (USR.Name, USR.AGE, USR.ID) del usuario USR donde usr.name =?"); Query.setString (0, "shun"); Vemos que este método es similar al de preparación que usamos directamente. Se establece a través del set ***, pero la diferencia es que la posición aquí comienza desde 0, mientras que la estación preparada comienza desde 1, así que preste especial atención aquí.
También hay un método de sesión de sesión en Hibernate2, pero como uso 3 ahora, no diré mucho al respecto.
El marcador de posición que utilizamos anteriormente se llama el marcador de posición de la orden, y hay otro llamado marcador de posición de referencia. Echemos un vistazo:
Query Query = Session.CreateQuery ("Seleccione nuevo usuario (usr.name, usr.age, usr.id) del usuario usr donde usr.name =: name"); query.setParameter ("nombre", "shun"); Vi que hay algo como: nombre en nuestra declaración HQL. Este es un marcador de posición de referencia. Solo necesitamos establecer el valor a través de SetParameter más tarde. Tenga en cuenta que el primer parámetro aquí debe corresponder al valor del marcador de posición en la instrucción HQL.
Por supuesto, algunas personas pueden decir que esto no está orientado a objetos, así que vamos a ser orientados a objetos nuevamente:
Primero, cree una clase para encapsular el valor que consultamos
Public Class UserQuery {Nombre de cadena privada; edad privada int; // omitir el método get/set} consulta de consulta = session.createQuery ("Seleccione nuevo usuario (usr.name, usr.age, usr.id) del usuario usr donde usr.name =: name"); UserQuery uq = new UserQuery (); uq.setName ("shun"); query.setProperties (uq); Encapsulamos los valores que necesitamos para consultar directamente a través de esta clase. Muy orientado a objetos.
Algunos equipos de proyectos tienen algunas regulaciones extrañas de que las declaraciones SQL no pueden aparecer en el código. Si esta es una especificación, entonces todos los códigos de nuestra empresa que he visto no están calificados. Muchos empalme de cuerda en la taza lo hacen parecer deprimido. Es realmente difícil estar herido en mantener los proyectos existentes.
Las declaraciones SQL no están permitidas en el código. Esta es una buena sugerencia, pero depende de la ocasión. Echemos un vistazo a cómo Hibernate configura HQL en los archivos de mapeo.
Mire directamente el archivo de configuración:
<query name = "QueryByName"> <! [CDATA [del usuario usr donde usr.name =: name]]> </Query>
Agregamos una etiqueta como esta, que indica que es una declaración HQL.
Cuando necesitamos obtener esta declaración, solo necesitamos agregar una oración al código:
Consulta consulta = session.getNamedQuery ("QueryByName"); De esta manera, se obtiene la declaración HQL.
HQL también se puede consultar utilizando combinaciones en SQL, como la unión interna, la unión exterior izquierda, la unión exterior derecha, la unión completa.
Echemos un vistazo a su uso:
Echemos un vistazo a la clase de entidad primero, lo que necesitamos usar en nuestras pruebas:
Public Class Tuser implementa serializable {privado estático final Long SerialVersionUid = 1L; ID privado int; edad privada int; nombre de cadena privada; Conjunto privado <dirección> direcciones = new Hashset <Diring> (); // omitir el método get/set} La dirección de clase pública implementa serializable {private static final long serialVersionUid = 1l; ID privado int; dirección de cadena privada; Usuario privado Tuser; // omitir el método get/set} Echemos un vistazo al archivo de asignación:
<hibernate-mapping paquete = "org.hibernate.tutorial.domain6"> <class name = "tuser" table = "t_user" dynamic-insert = "true" dynamic-update = "true"> <id name = "id" columna = "id"> <generador/>> </id> <property name = "name" type = "java.lang.string" columna "columna" columna " name = "Age" type = "java.lang.integer" column = "edad"/> <set name = "direcciones" cascade = "all" table = "t_address" inverse = "true"> <key column = "user_id"/> <uno- uno a-many/> </set> </class> </hibercapenate-mapping> <iacernado paquete = "org.hibernate.tutorial.domain6"> <class name = "dirección" table = "t_address" dynamic-insert = "false" dynamic-update = "false" dynamic-update = "false" dynamic-update = "id" type = "java.lang.integer"> <generador /> < /id> <sperty = "dirección de la columna =" columna "columna" "columna" " type = "java.lang.string"/> <Many-to-one name = "user" column = "user_id" no-null = "true"> </ingle- to-one> </class> </hibernate mapping>
Solo necesita modificar el nombre del paquete correspondiente.
Realicemos pruebas formales:
Antes de la prueba, veamos los datos en la tabla:
Los datos de la tabla T_Address son los siguientes:
Los datos de la tabla T_USER son los siguientes:
1) Primero, echemos un vistazo a la unión interna, que es obtenida en HQL por Inner Join Fetch. Tenga en cuenta que el significado de obtener aquí es obtener los datos requeridos. Si no se usa una recuperación, los datos que obtuvimos son del tipo de datos del objeto [].
Echemos un vistazo primero
De Tuser USR Inner Join Fetch Usr. Addresses
Cuando lo ejecutamos, vemos que la salida hibernada es:
Hibernate: seleccione Tuser0_.id como id1_0_, direcciones1_.id como id0_1_, tuser0_.name as name1_0_, tuser0_.age como Age1_0_, direcciones1_.address como direcciones 0_1_, direcciones1_.user_id as user3_0_1_, direcciones1_.id as id0__ direcciones t_address1_ en tuser0_.id = direcciones1_.user_id
Podemos ver los resultados cuando se ejecutan en MySQL:
Podemos ver que Hibernate lo convierte en una declaración de unión interna y descubre la dirección.
Vemos que no hay registro de shun4 en el resultado, porque no tiene la dirección y el registro correspondientes.
Cuando usamos la unión interna en lugar de buscar, la declaración que imprime es:
Hibernate: seleccione Tuser0_.id como id1_0_, direcciones1_.id como id0_1_, tuser0_.name as name1_0_, tuser0_.age como Age1_0_, direcciones1_.address como direcciones0_1_, direcciones1_.user_id as user3_0_1_ desde t_user tuser0_ inner se une tuser0_.id = direcciones1_.user_id
Parece que la declaración no es diferente, pero cuando la encontramos, obtiene un tipo de matriz de objeto [], por lo que debe prestar atención a este análisis.
Cuando no usamos Fetch sino solo unión interna, necesitamos analizarlo así:
Consulta consulta = session.createQuery ("De Tuser USR Inner se une a USR.Addresses"); List list = query.list (); Iterator iter = list.iterator (); while (iter.hasnext ()) {object [] resultados = (objeto []) iter.next (); for (int i = 0; i <results.length; i ++) {system.out.println (resultados [i]); }} Vemos el resultado de la impresión:
org.hibernate.tutorial.domain6.tuser@16925b0 org.hibernate.tutorial.domain6.address@914f6a org.hibernate.tutorial.domain6.tuser@787d6a org.hibernate.tutorial.domain6.address@71dc3d org.hibernate.tutorial.domain6.tuser@1326484 org.hibernate.tutorial.domain6.address@16546ef
Cada uno de sus resultados es el objeto correspondiente.
2) Unión externa izquierda, esto es equivalente a la conexión izquierda de SQL. Echemos un vistazo al ejemplo directamente:
De Tuser USR Izquierda Exterior Join Fetch USR. Addresses
Cuando ejecutamos la declaración anterior, Hibernate se imprime:
Hibernate: seleccione Tuser0_.id como id1_0_, direcciones1_.id como id0_1_, tuser0_.name as name1_0_, tuser0_.age como age1_0_, direcciones1_.address como direcciones 0_1_, direcciones1_.user_id as user3_0_1_, direcciones1_.id como id0__ unirse a las direcciones T_address1_ en tuser0_.id = direcciones1_.user_id
Lo revisamos en mysql y vimos:
Vemos que aunque Shun4 no tiene una dirección correspondiente, todavía se descubre. La unión externa izquierda se refiere a descubrir todos los registros en la mesa izquierda.
No hablaré de la situación sin buscar aquí.
3) Luego, echemos un vistazo a la unión exterior derecha. A juzgar por el nombre, debe estar relacionado con la unión externa izquierda. Podemos verlo claramente mirando los ejemplos directamente.
De Tuser USR Right Outer Join Fetch Usr. Addresses
Lo ejecutamos y obtenemos la salida de la declaración de resultados de Hibernate es:
Hibernate: seleccione Tuser0_.id como id1_0_, direcciones1_.id como id0_1_, tuser0_.name as name1_0_, tuser0_.age como age1_0_, direcciones1_.address como direcciones 0_1_, direcciones1_.user_id como user3_0_1_, direcciones1_.id como id0__ unirse a las direcciones T_address1_ en tuser0_.id = direcciones1_.user_idPodemos ver los resultados después de ejecutar en MySQL:
Aquí podemos ver que la dirección es Test4 y no tiene el usuario correspondiente correspondiente a ella, pero aún se descubre. La unión exterior derecha se refiere a descubrir todos los registros en la tabla correcta.
La situación de la búsqueda es la anterior. Si no lo entiende, puede echar un vistazo a Inner Join Fetch.