La investigación en este artículo se centra principalmente en el mecanismo de caché hibernado, como sigue.
Student.java:
Estudiante de clase pública {/*estudiante id*/private int id;/*nombre de estudiante*/name de cadena privada;/*relación entre estudiantes y clases*/clases privadas; // omitir los métodos setter y getter}Classes.java:
clases de clase pública {/*class id*/private int id;/*nombre de clase*/name de cadena privada;/*relación entre clase y estudiantes*/set privado <estudiante> estudiantes; // omitir los métodos de setter y getter}Estudiante.hbm.xml:
<? xml versión = "1.0"?> < table = "t_student"> <id name = "id"> <generador // id> <!-Map Propiedades normales-> <propiedad name = "name"/> <!-Mappes de muchos a uno, agregue una clave extranjera al final múltiple-> <muchos a uno name = "classes" column = "classesid"/> </sclass> </bercernate-mapping>
Classes.hbm.xml:
<? xml versión = "1.0"?> < <class name = "classes" table = "t_classes" lazy = "false"> <id name = "id"> <generador/generador/> </id> <propiedad name = "name"/> <!-One-to-many mapping, inverse = "true" verdadero para entregar la relación a la pareja-> <name de set = "estudiantes" inverse = "verdadero"> <play columna = "columna =" classid "/"/" </set> </sclass> </ Hibernate Mapping>
El período de declaración del caché de primer nivel es muy corto y el ciclo de vida de la sesión es consistente. El caché de primer nivel también se llama caché de nivel de sesión o caché de nivel de cosas. El caché de primer nivel es el objeto de caché y no puede almacenar atributos.
Método de prueba (usar la consulta Load () dos veces en la misma sesión):
/*Después de sacarlo, se colocará en el caché, y la segunda vez que obtiene se recuperará directamente del caché*/ estudiante estudiantil = (estudiante) session.load (student.class, 1); System.out.println ("student.name =" + student.getName ()); /*No se emite una declaración de consulta, la carga usa caché*/ estudiante = (estudiante) session.load (student.class, 1); System.out.println ("student.name =" + student.getName ());Nota: Encontraremos que cuando la consulta por primera vez, los resultados encontrados se colocarán en sesión, caché y caché de nivel uno. Cuando obtengo el valor en el tiempo después de la carga () la segunda vez, no emití una declaración para consultarlo en la base de datos, pero recuperé directamente el valor del caché (debe estar en la misma sesión).
Método de prueba dos (en la misma sesión):
Estudiante estudiante = nuevo estudiante (); Student.SetName ("Zhang San"); Serializable id = session.save (estudiante); estudiante = (estudiante) Session.Load (Student.Class, ID); // La declaración de consulta no se emitirá porque Save admite caché System.out.println ("student.name =" + student.getName ());NOTA: El método Save () se llama y load () se usa para cargar el objeto, y luego el atributo de nombre realmente se obtiene, pero no se emite ninguna declaración para consultar la base de datos. Porque el método Save () también admite caché.
Pruebe la adición de grandes lotes de datos:
public void testCache7 () {session session = null; intente {session = hibernateUtils.getSession (); session.BeginTransaction (); para (int i = 0; i <100; i ++) {Student Student = New Student (); student.setName ("Zhang San" + i); Session.save (estudiante); // Actualiza cada 20 elementos si (i % 20 == 0) {// Borrar el caché, y después de llamar a Flush, los datos se guardarán en la base de datos Session.Flush (); // borrar el contenido en caché session.clear (); }} session.getTransaction (). commit (); } catch (Exception e) {E.PrintStackTrace (); session.getTransaction (). Rollback (); } finalmente {hibernateUtils.clossessession (sesión); }} Nota:
1. Debido a que el método Save () admite caché, hay un problema. Si quiero ahorrar 10 millones de datos al mismo tiempo, entonces hay 10 millones de objetos de caché en el caché, lo que probablemente cause desbordamiento. Por lo tanto, Hibernate no admite la operación de actualización de datos a gran escala, pero también podemos manejar este problema de manera muy flexible, como borrar el caché cada 20 piezas de datos utilizando un bucle.
2. Guardar, actualizar, salvar, obtener, cargar, obtener, listar, iterar, los métodos de bloqueo pondrán objetos en el caché de primer nivel. El caché de primer nivel no puede controlar el número de cachés, por lo que debe prestar atención a la posibilidad de desbordamiento de la memoria al operar datos en lotes grandes; Puede usar el método desalojo y claro para borrar el contenido en el caché.
El caché secundario también se llama caché de nivel de proceso o caché de nivel de sesión de sesión, y el caché secundario puede ser compartido por todos los cachés de sesión. El ciclo de vida del caché secundario es el mismo que el de SessionFactory. SessionFactory puede administrar el caché secundario. El principio del caché secundario se usa cuando la lectura es mucho mayor que la escritura. El caché secundario se usa principalmente para almacenar objetos de entidad.
1. Copie el archivo ehcahe.xml al directorio SRC.
2. Agregue el proveedor de productos de caché al archivo hibernate.cfg.xml, como sigue:
<propiedad name = "hibernate.cache.provider_class"> org.hibernate.cache.ehcacheprovider </property>
3. Habilite el caché de nivel 2 (no se puede mostrar el inicio, porque el valor predeterminado está habilitado), de la siguiente manera:
<propiedad name = "hibernate.cache.use_second_level_cache"> verdadero </sperty>
4. Especifique qué clases de entidad usan la memoria caché de nivel 2.
5. Importe el paquete JAR de interfaz utilizado por el caché: lib/optional/ehcache/ehcache-core-2.4.3.jar
Contenido del archivo ehcache.xml:
<DefaultCache maxelementsInmemory = "10000" eternal = "false" timetoidleseConds = "120" TimetoliveSeconds = "120" OverflowTodisk = "True" />
Nota:
1.MaxelementsInMemory representa los objetos más almacenados en el caché.
2. Eternal indica si nunca caducará (establecerlo en falso es más práctico. Si es cierto, nunca caducará, entonces los siguientes atributos no tienen sentido).
3.TimetoidlesEcods indica cuánto tiempo no se ha accedido a un objeto después de la primera vez que se ha eliminado.
4. TimetoliveCods representa el tiempo de inventario de un objeto.
5. OverflowTodisk es verdadero, lo que significa que el número en el caché excede el número especificado por MaxElementSInMemory y se almacena en el disco.
Especifique la ruta del disco guardada en el desbordamiento:
<diskstore path = "java.io.tmpdir"/>
Nota: Este camino se puede cambiar.
Método de prueba (la premisa de la memoria caché de nivel 1 es que debe estar en la misma sesión. Ahora usamos la memoria caché de nivel 2 para ver si hay un caché en dos sesiones diferentes):
public void testCache1 () {session session = null; try {session = hibernateUtils.getSession (); session.beginTransaction (); estudiante estudiante = (estudiante) session.load (student.class, 1); system.out.println ("student.name =" + student.getName ()); session.getTransaction (). comision ();} Catch (excepción) {E.PrintStackTrace (); session.getTransaction (). rollback ();} finalmente {hibernateUtils.clossessession (session);} try {session = hibernateUtils.getSession (); session.beGinTransaction (); estudiante estudiante = (estudiante) session.load (estudiante puede compartir los datos en la memoria caché secundaria .//the Secondary Cache es un caché de nivel de proceso System.out.println ("student.name =" + student.getName ()); session.getTransaction (). commit ();} capt (excepción e) {e.printstacktRace (); session.getTransaction (). {HibernateUtils.clossession (sesión);}}Nota: Si el caché secundario está configurado, encontraremos que incluso si la primera sesión está cerrada y se enciende otra sesión para cargar datos, no emitirá una declaración para consultar los datos en la base de datos, porque el caché secundario está configurado, está compartido por toda la sesión de sesión.
Deshabilitar la memoria caché de nivel 2 para implementar la adición de grandes lotes de datos:
public void testCache5 () {session session = null; intente {session = hibernateUtils.getSession (); session.BeginTransaction (); // La interacción de caché de línea y caché secundario está prohibido session.setCachemode (Cachemode.ignore); para (int i = 0; i <100; i ++) {Student Student = New Student (); student.setName ("Zhang San" + i); Session.save (estudiante); // actualiza cada 20 elementos si (i % 20 == 0) {session.flush (); // Clear en caché de contenido session.clear (); }} session.getTransaction (). commit (); } catch (Exception e) {E.PrintStackTrace (); session.getTransaction (). Rollback (); } finalmente {hibernateUtils.clossessession (sesión); }}Nota: Session.Flush () significa borrar el caché de primer nivel, pero hemos comenzado el caché de segundo nivel nuevamente, y después de guardar (), también lo guarda al caché de segundo nivel, pero todavía hay un desbordamiento causado por un caché excesivo. Entonces, en este caso, debemos deshabilitar el caché secundario: session.setCachemode (Cachemode.ignore);
Cache de consulta: tanto el caché de nivel de primer nivel como el caché de caché de segundo nivel, ambos objetos de la entidad de caché, pero a veces esperamos obtener ciertos atributos y no accedamos con frecuencia a la base de datos, pero obtenga el caché. En este momento, podemos usar el caché de consulta. Además, los conjuntos de resultados de caché de consultas para objetos de entidad cachearán ID. Se cambia el ciclo de vida del caché de la consulta. Cuando se modifica la tabla asociada, termina el ciclo de declaración del caché de consulta, que no tiene nada que ver con el ciclo de vida de la sesión.
1. Modifique el archivo hibernate.cfg.xml para habilitar la memoria caché de consultas. Si False es predeterminado, no está habilitado. Debe establecerse de la siguiente manera:
<propiedad name = "hibernate.cache.use_query_cache"> true </propiedad>
2. Debe estar habilitado en el programa, como:
Query.setCacheable (verdadero)
Método de prueba:
public void testCache2 () {session session = null; try {session = hibernateUtils.getSession (); session.begintransaction (); list names = session.createquery ("seleccione s.name del estudiante") .SetCacheable (true) .List (); for (int i = 0; i <names.size (); i ++) {name de cadena = (String) Names.get (i); System.out.println (name);} session.getTransaction (). Commit ();} Catch (Exception e) {E.PrintStackTrace (); session.getTransaction (). Rollback ();} Finalmente {HibernateUtils.clossessession (sesión);} system.out.println ("------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ----------------------------------------------------------------------------------------------- .list (); for (int i = 0; i <names.size (); i ++) {string name = (string) names.get (i); system.out.println (name);} session.getTransaction (). commit ();} catch (excepción e) {E.PrintStackTrace (); session.getTransaction (). Rollback ();} finalmente {HibernateUtils.clossession (sesión);}}Nota: En el código anterior, apagamos el caché secundario, encendemos el caché de consulta y luego consultamos las propiedades normales. Ejecute el código de prueba y podemos encontrar que en la primera sesión, la primera consulta emite una declaración, luego cierra la sesión y luego consulta en la segunda sesión. Encontraremos que la consulta en la segunda sesión no emite una declaración, lo que significa que el caché de la consulta no tiene nada que ver con el ciclo de vida de la sesión.
Configuración de caché de hibernate.cfg.xml:
< name = "net.sf.ehcache.configurationResourCename">/ehcache.xml </propiation> <!-Establezca el caché usando la consulta-> <propiedad name = "hibernate.cache.use_Query_cache"> true </property> <!-Cargue el archivo de mapeo de la relación de objetos-> <mapping recurso = "com/lixue/classes. <mapping recource = "com/lixue/bean/student.hbm.xml"/> <!-El archivo de asignación de recursos (es decir, el archivo de asignación de entidad) debe introducirse antes de configurar una clase de entidad usando el caché de nivel 2-> <class-cache use = "lectura"/>>
Lo anterior es todo el contenido de este artículo sobre el análisis del código de los ejemplos de mecanismo de caché de hibernación, espero que sea útil para todos. Los amigos interesados pueden continuar referiéndose a otros temas relacionados en este sitio. Si hay alguna deficiencia, deje un mensaje para señalarlo. ¡Gracias amigos por su apoyo para este sitio!