Interceptador
Hablando de Interceptor, creo que los zapatos de los niños familiarizados con Struts2 definitivamente están familiarizados con Struts2. Struts2 puede personalizar al interceptor para realizar una serie de trabajos relacionados que desea. Y el interceptor del que estamos hablando aquí también tiene funciones similares.
Sin decir tonterías, solo código:
La siguiente es la clase MyInterceptor, que implementa la interfaz del interceptor:
public String onPrepareStatement (String arg0) {return arg0; } public boolean onsave (Object arg0, serializable arg1, object [] arg2, string [] arg3, type [] arg4) lanza CallBackException {if (arg0 instanceof user) {system.out.println ("usuario para guardar =>"+((usuar) arg0) .getName ()); } return false; } No leeré otros métodos, solo siga la implementación predeterminada. Solo necesitamos cambiar estos dos métodos. Necesitamos cambiar el valor de retorno en OnPrepareStatement para devolver la instrucción SQL actual. Los parámetros son la declaración SQL ejecutada aprobada. Podemos imprimir la declaración devolviéndola directamente.
En Onsave, puedes decir que se llama al ahorrar. Podemos hacer una serie de trabajos previos a la conservación.
Creo que todos pueden entenderlo mirando los nombres de los parámetros.
Serializable se refiere al parámetro del número de secuencia, que se refiere a los atributos que mapean a la ID de base de datos.
Objeto [] Este es una serie de estados, que no se ha utilizado mucho por el momento. Lo estudiaré más tarde. Sin embargo, la API explica que no importa cómo se modifique el valor en esta matriz, el método ONSAVE debe devolver verdadero.
La cadena [] se refiere al nombre del atributo y el tipo [] es el tipo del atributo correspondiente.
1) Este interceptor puede hacer algunas operaciones correspondientes antes y después de guardar la base de datos. Por ejemplo, si desea modificar los datos y agregar prefijo o sufijo, puede usarlos para implementarlos. Echemos un vistazo a continuación.
Public Boolean Onsave (Object arg0, serializable arg1, object [] arg2, string [] arg3, type [] arg4) lanza CallBackException {if (arg0 instanceof user) {system.out.println ("usuario para guardar =>"+((usuario) arg0) .getName ()); } // agregamos 123 como prefijo del nombre aquí user user = (usuario) arg0; user.setName ("123"+user.getName ()); devolver falso; }Echemos un vistazo al método de prueba:
public static void main (string [] args) {Configuration cfg = new Configuration (). Configuración (); SessionFactory sessionFactory = cfg.BuildSessionFactory (); Interceptor interceptor = new MyInteceptor (); Sesión Session = SessionFactory.Opensession (Interceptor); Usuario user = nuevo usuario (); user.setName ("shun"); Transacción tx = session.beGinTransaction (); session.save (usuario); tx.commit (); session.close (); } Es muy simple, lo guardamos simplemente. No hay archivos de mapeo y clases de entidad aquí, solo pruébelo.
Ejecutarlo y podemos ver:
El usuario se guardará => shun hibernate: inserte en valores de usuario (user_name, edad) (?,?) Hibernate: actualizar user set user_name =?, Edad =? ¿Dónde user_id =?Actualizará el nombre y la edad al final, principalmente porque hemos realizado cambios en el método Onsave.
Public Boolean Onload (Object Arg0, Serializable Arg1, Object [] Arg2, String [] arg3, type [] arg4) lanza CallBackException {if (arg0 instanceof user) {system.out.println ("usuario para cargar =>"+(arg2 [0]+":"+arg2 [1])); } Usuario user = (usuario) arg0; // juzga qué atributo es nombre para (int i = 0; i <arg3.length; i ++) {if (arg3 [i] .equals ("name")) {user.setName ((string) arg2 [i]). Reemplazar ("123", "")); arg2 [i] = ((string) arg2 [i]). reemplazar ("123", ""); }} return false; } El valor del atributo modificado al cargar se escribe en el método de Onload.
El arg0 aquí es nuestro objeto de usuario. Todavía no tiene valor. Este método se llama después del método de carga, por lo que es inútil para nosotros operar al usuario en este momento, y el user.setName aquí es una operación inútil. Principalmente en:
arg2 [i] = ((string) arg2 [i]). reemplazar ("123", "");
Este código cambia el valor del atributo devuelto, por lo que el valor en el objeto de usuario que obtenemos en el programa también cambiará. Ejecutemos el método de prueba para ver:
public static void main (string [] args) {Configuration cfg = new Configuration (). Configuración (); SessionFactory sessionFactory = cfg.BuildSessionFactory (); Interceptor interceptor = new MyInteceptor (); Sesión Session = SessionFactory.Opensession (Interceptor); Usuario user = (usuario) session.load (user.class, nuevo largo (39)); System.out.println ("Nombre de usuario:"+user.getName ()); session.close (); }Mirando los resultados, obtuvimos:
Hibernate: seleccione User0_.user_id como user1_0_0_, user0_.user_name como user2_0_0_, user0_.age como Age0_0_ de User User0_ donde user0_.user_id =? El usuario se cargará => 123shun: 0 Nombre de usuario: Shun
Hemos eliminado el 123 original y llevado a cabo un procesamiento relevante después de la carga real, pero este no es un procesamiento real antes de la carga real, y sospecha un poco de especulación. Pero también es una consideración. El interceptor se puede usar más en el procesamiento relevante de los registros. Por ejemplo, necesitamos registrar correspondientemente para cada operación, por lo que el interceptor es una buena opción.
Recopilación
Recuerde el conjunto que usamos en uno a muchos en los ejemplos anteriores, ¿todavía tiene la impresión? Si no lo hace, visite la información y revise. Hoy aprenderemos sobre estas colecciones.
Vamos al punto.
1) Primero aprendamos set. Todos saben que también hay un conjunto en el paquete Java Util. Entonces, ¿cuál es la diferencia y la conexión entre Set y Set en Hibernate? Abrimos la API Hibernate, Encontramos set, y puedes verlo.
Lo que vemos es la clase madre de una colección de este tipo hibernada. Es una clase abstracta con una serie de clases de implementación concretas. Cuando continuamos viendo el siguiente método, encontramos que esta clase implementa la encapsulación de la colección Java, por lo que entendemos que el llamado conjunto Hibernate en realidad solo encapsula el conjunto de Java.
Entonces, ¿es esta característica que no permite elementos duplicados en SET también en Hibernate? La respuesta es, por supuesto, sí.
No miramos estos aquí. En el pasado, cuando aprendimos el mapeo, asociamos directamente propiedades con las clases asociadas, pero hoy no somos así. Usamos otro método, solo asociamos una cadena para ver si hay algún problema.
Pero antes de mirar esta pregunta, echemos un vistazo a la comparación de cuerdas en Java.
Lo que vemos es la clase madre de una colección de este tipo hibernada. Es una clase abstracta con una serie de clases de implementación concretas. Cuando continuamos viendo el siguiente método, encontramos que esta clase implementa la encapsulación de la colección Java, por lo que entendemos que el llamado conjunto Hibernate en realidad solo encapsula el conjunto de Java.
Entonces, ¿es esta característica que no permite elementos duplicados en SET también en Hibernate? La respuesta es, por supuesto, sí.
No miramos estos aquí. En el pasado, cuando aprendimos el mapeo, asociamos directamente propiedades con las clases asociadas, pero hoy no somos así. Usamos otro método, solo asociamos una cadena para ver si hay algún problema.
Pero antes de mirar esta pregunta, echemos un vistazo a la comparación de cuerdas en Java.
public static void main (string [] args) {string s1 = "shun1"; Cadena s2 = "shun1"; System.out.println ("S1 == S2:"+(S1 == S2)); } Creo que los zapatos de muchos niños saben que la respuesta es cierta.
Antes de hacer un ejemplo, echemos un vistazo a nuestro archivo de mapeo. No escribiremos las clases de mapeo:
Este es el archivo de asignación para Tuser:
<class name = "tuser" table = "t_user" dynamic-insert = "true" dynamic-update = "true" dynamic-update = "true"> <id name = "id" column = "id"> <generador/> </id> <propiedad name = "name" type = "java.lang.string" columna = "name"/> <name de propiedad = "edad" type = "java.lang.lang.lang.lang.lang.lang.lang" javeGer " columna = "edad"/> <set name = "direcciones" cascade = "all" table = "t_address"> <key column = "user_id"/> <!-<One-o-many/>-> <elemento columna = "dirección" type = "string"/> </set> </class>>
El siguiente es el archivo de asignación de direcciones:
<class name = "dirección" table = "t_address" dynamic-insert = "false" dynamic-update = "false"> <id name = "id" column = "id" type = "java.lang.integer"> <generador /> < /id> <ideal = "Property" dirección "columna =" dirección "type =" java.lang.string " /> <nlegue-one name" User "User" User "User" User "User" User " no-null = "true"> </ingle-to-one> </sclass>
Los zapatos de los niños lo han visto claramente. Comenté uno a muchos en el set en Tuser y el elemento usado. No importa cuál sea el problema, veamos primero la base de datos:
Esta es la tabla T_address:
Aquí está la tabla T_user:
Podemos ver que el usuario con ID 4 corresponde a tres direcciones. A continuación, echemos un vistazo al método de prueba:
public static void main (string [] args) {Configuration cfg = new Configuration (). Configuración (); SessionFactory sessionFactory = cfg.BuildSessionFactory (); Sesión session = sessionFactory.opensession (); Tuser user = (Tuser) Session.Load (Tuser.Class, New Integer (4)); Set set = user.getAddresses (); session.close (); System.out.println ("Tamaño de dirección:"+set.size ()); } Una clase de consulta muy simple, solo sacó este resultado, vimos un fenómeno extraño:
Tamaño de la dirección: 1
¡Este es el resultado!
Definitivamente dirás que debe estar mal, es un error en Hibernate. Debo ser feliz aquí. Finalmente puedo enviar un error. Cuando cambié de trabajo, podría decir en voz alta que envié un error para Hibernate. Jaja, pero desafortunadamente, esto no es un error.
Acabo de decir que la comparación de la cuerda que teníamos frente a los que estaba allanando el camino aquí, entonces, ¿cómo pavimentarla?
Usamos establecer en el archivo de configuración y asociarlo a través de caracteres de cadena. Luego, cuando se saca en la base de datos y la coloca en el conjunto, primero determinará si los valores del carácter asociado son iguales. Aquí, dado que nuestros valores son iguales (no profundizaremos en cómo se compara por el momento), solo necesitamos saber que cuando usamos cadenas para comparar, caemos en la trampa de cadena en Java nuevamente. Si descubre que solo hay uno, entonces la eliminación es más problemática al eliminarlo, eliminará los mismos registros.
Entonces echemos un vistazo al eliminado:
Tuser user = (Tuser) Session.Load (Tuser.Class, New Integer (4)); Transacción tx = session.beGinTransaction (); Object obj = user.getAddresses (). Iterator (). Next (); user.getAddresses (). Retir (obj); tx.commit (); session.close ();
El resultado de la declaración de Hibernate aquí es:
Hibernate: Eliminar de t_address donde user_id =?
Creo que todos saben cuándo es eliminar todas las direcciones bajo el usuario. No hay más remedio que eliminar todo esto.
Por lo tanto, debe prestarle atención en el desarrollo real.
2) Hablamos sobre el conjunto anterior, parece que no es muy agradable de usar. Hay tal trampa, pero no hay forma. El conjunto es el que más usamos, y generalmente nadie asociará directamente las cadenas. Pero muchas personas todavía están infelices, por lo que Hibernate tendrá una bolsa extra según sea necesario (tal vez no como sea necesario, tal vez algunas personas en ellas están insatisfechas, jaja).
Primero veamos su uso básico:
Primero, necesitamos modificar la etiqueta establecida en el archivo de asignación de tusores anterior a:
<bag name = "direcciones" lazy = "true" table = "t_address"> <key column = "user_id" /> <element type = "string" column = "dirección" /> </bag>
Y la clase de entidad correspondiente debe modificar el tipo de direcciones al tipo de lista.
Aquí agregamos tres direcciones:
Ejecutamos el código de prueba:
public static void main (string [] args) {Configuration cfg = new Configuration (). Configuración (); SessionFactory sessionFactory = cfg.BuildSessionFactory (); Sesión session = sessionFactory.opensession (); Tuser user = (Tuser) Session.Load (Tuser.Class, New Integer (4)); System.out.println ("Tamaño de la dirección:"+user.getAddresses (). Size ()); session.close (); }
Aquí vemos:
Tamaño de la dirección: 3
Esta vez podemos verlo todo, independientemente de si hay repeticiones o no.
Pero solo miramos un problema de eliminación. La bolsa no se ha resuelto aquí, y necesitamos usar Idbag. Vemos el archivo de configuración y necesitamos las siguientes modificaciones:
Idbag name = "Directes" table = "t_address" lazy = "true"> <collection-id type = "int" column = "id"> <generator /> < /collection-id> <key columna = "user_id" /> <element type = "string" column = "dirección" /> </idbag>>
Vemos que solo tiene una colección más que la bolsa para indicar el número de registro que se eliminará.
Cuando volvemos a ejecutar el código eliminado:
Tuser user = (Tuser) Session.Load (Tuser.Class, New Integer (4)); Transacción tx = session.beGinTransaction (); Object obj = user.getAddresses (). Iterator (). Next (); user.getAddresses (). Retir (obj); tx.commit ();
Vemos que la declaración de salida es:
Hibernate: Eliminar de t_address donde id =?
Esta vez, no se elimina a través de USER_ID, sino en función de la ID de T_address, lo que significa que realmente elimina el registro que necesitamos eliminar.
Vemos la base de datos y el registro es ahora:
Hemos eliminado el primer registro, es correcto.
3) Después de mirar los dos métodos anteriores, echemos un vistazo al mapa. La mayor diferencia entre él y los dos anteriores es que puede corresponder a valores clave. Mire directamente el código, punto de vista intuitivo:
Primero, necesitamos modificar el archivo de configuración:
<map name = "direcciones" table = "t_address" lazy = "true"> <key column = "user_id" /> <index type = "string" column = "type" /> <element type = "string" column = "dirección" /> < /map>
La mayor diferencia entre él y los dos anteriores es que hay un índice, que es equivalente a la tecla MAP en Java, y usamos esto para recuperar los registros correspondientes. Recuerde, después de cambiar aquí, debe cambiar la clase de entidad correspondiente y debe cambiar el tipo de atributo de direcciones al mapa.
Mire los datos de la base de datos:
Aquí vemos que hay dos oficinas y una casa, entonces, ¿qué oficina se debe usar?
No se preocupe, lo sabremos después de ejecutar el código de prueba:
Tuser user = (Tuser) Session.Load (Tuser.Class, New Integer (4)); System.out.println (user.getAddresses (). Get ("inicio")); System.out.println (user.getAddresses (). Get ("oficina"));Shanwei Shanghai
Sí, como muestra el resultado, tenemos el uno detrás, que es el mismo que el principio del mapa. Los valores almacenados sobrescribirán los valores anteriores (si son la misma clave).
El mapa es relativamente simple, que es comparable a los dos primeros.
4) Echemos un vistazo al último. La lista es diferente de las anteriores, y se puede ordenar.
Echemos un vistazo a cómo se implementa:
Primero, modificemos el archivo de asignación:
<list name = "direcciones" table = "t_address" lazy = "true"> <key column = "user_id" /> <index type = "string" column = "idx" /> <element type = "string" column = "dirección" /> < /list>
Es similar a la configuración de MAP, pero los atributos del índice son diferentes. El índice en el mapa se usa como clave para obtener el valor, mientras que el índice de la lista se usa como clasificación.
Veamos la base de datos:
Establecimos tres valores en el orden de 0, 1 y 2.
Ejecutemos el código para cambiar los valores de 0 y 2:
Tuser user = (Tuser) Session.Load (Tuser.Class, New Integer (4)); Transacción tx = session.beGinTransaction (); Objero obj1 = user.getAddresses (). Get (0); Objero obj2 = user.getAddresses (). Get (2); user.getAddresses (). set (0, obj2); user.getAddresses (). set (2, obj1); tx.commit ();
Vemos los resultados:
Vemos que 0 y 2 han sido reemplazados y, por supuesto, esto solo está cambiando el valor de IDX. Pero esto básicamente ha implementado la función de clasificación.