La principal investigación en este artículo es el nivel de session_flush de Hibernate y el nivel de aislamiento. La introducción y los ejemplos específicos son los siguientes.
Veamos primero algunos conceptos:
1. Lectura sucia: la lectura sucia también se llama la lectura de datos no válidos. Significa que durante el acceso a la base de datos, la cosa T1 modifica un cierto valor, y luego la cosa T2 lee el valor. Después de eso, T1 cancela la modificación del valor por alguna razón, lo que hace que los datos leídos por T2 no sean no válidos. La lectura sucia significa que cuando una cosa está accediendo a los datos y modifica los datos, y esta modificación no se ha enviado a la base de datos, otra cosa también accede a estos datos y luego usa estos datos. Debido a que estos datos aún no se envían, los datos leídos por otra cosa son los datos sucios, y las operaciones realizadas en función de los datos sucios son incorrectos.
2. No es lectura repetida: por ejemplo, cuando estaba leyendo una publicación, los datos que encontré eran Zhang San y Li Si. Luego, después de renovarme, descubrí que el Zhang San inicial se convirtió en Zhang Ba. Esta es la llamada lectura no repetible, porque los datos que leí no se repitieron.
3. Lectura de fantasía: cuando estaba buscando los datos, comencé a encontrar 3 registros. Cuando lo refresqué, descubrí que los registros se convirtieron en 8. Esta es una lectura de fantasía.
4. Envíe la lectura: solo puede leer después de enviar. Oracle predeterminado a esto. No hay lectura sucia de esta manera.
5. Repetibilidad: obviamente es lo opuesto a la lectura no repetible. Puede evitar la lectura no repetible, pero esto no puede evitar la lectura fantasma.
6. Serialización: este método es muy estricto. En términos de Layman, cuando estoy haciendo algo, nadie más puede hacerlo. Es muy seguro, pero es extremadamente ineficiente.
A continuación utilizamos ejemplos prácticos para comprender la aplicación de la autorización de caché de hibernación.
La base de datos de mapeo de hibernación está relacionada con la estrategia de generación de clave principal.
Ejemplos de generación de claves primarias en UUID:
Usuario de clase pública {private string uid; private string uname; private date cumpleaños; public string getuid () {return uid;} public void setUid (string uid) {this.uid = uid;} public String getuname () {return uname;} public void setuname (String uname) setBirthday (cumpleaños de fecha) {this.birthday = cumpleaños;}}User.hbm.xml:
<? xml versión = "1.0"?> < paquete = "com.lixue.bean"> <!-El nombre del nodo de clase representa el nombre de clase de la entidad, y la tabla representa el nombre de la entidad asignada a la tabla en la base de datos-> <class name = "user" table = "t_user"> <id name = "uid"> <!-generado a través de uuid-> <generador/> </d> <name de propiedad " name = "Cumpleaños"/> </class> </hibernate-mapping>
Método de prueba:
/ ***Pruebe la estrategia de generación de claves primarias de UUID*/ public void testSave1 () {/*Sesión definida y cosas*/ session session = null; Transacción transacción = nulo; Pruebe { /*Get Session y Things* / Session = HibernateUtil.getSession (); transacción = session.beGinTransaction (); /*Crear usuario*/ usuario user = new User (); user.setUname ("xi jinping"); user.setBirthday (nueva fecha ()); / *** Debido a que la estrategia de generación de clave principal del usuario es UUID, después de llamar a guardar, solo incluye al usuario en la administración de sesión* La instrucción Insertar no se emitirá, pero la ID se ha generado y el estado existentes en la base en persistenceContext es falso*/ session.save (usuario); /** * Llamando a Flush, Hibernate limpiará el caché (inserte los objetos en la colección temporal en sesión-> Insercios en la base de datos, borrando la colección temporal) * En este momento, los datos no se pueden ver en la base de datos, pero si el nivel de aislamiento de la base de datos no se envía a leer, * luego podemos ver los datos en busca y el estado de las existencias de la existencia. session.flush (); /** * Enviar cosas * Por defecto, la operación de confirmación realizará la caché de limpieza de descarga, * por lo que los datos no se pueden volver después de llamar a Flush sin pantalla * commit * transaccion.ComMit (); } catch (Exception e) {E.PrintStackTrace (); transacción.rollback (); } finalmente {hibernateUtils.clossessession (sesión); }} Podemos depurar el programa a través de puntos de interrupción:
1. Dado que la tasa lateral de la generación de clave principal del usuario es UUID, después de llamar al método save (), el objeto de usuario solo se puede incluir en la administración de la sesión, y la declaración de inserción no se emitirá, pero la identificación se ha generado (nota: dos lugares son muy importantes después de que primero, primero, hay un elemento en la sesión-> Actionqueue-> Insertions-> ElementData Change que almacena nuestro objeto. Esto es un objeto de cobro temporal. PersistenceContext-> EntityEntries-> MAP-> TABLE-> Un cierto elemento de matriz-> Value almacena el objeto. Como se muestra en la imagen:
2. Después de llamar al método FLUSH (), el valor almacenado temporal de ActionQueue en la sesión se borrará, y luego el valor de ExistSindAbase en la PersistenContext se establece en True, lo que indica que hay datos correspondientes en la base de datos en este momento, pero al abrir la base de datos y abrir la tabla, no puede ver los datos, ya que el nivel de isolio predeterminado de nuestra base de datos mySQL es un comodidad de la base de datos mySQL. datos. Después de llamar al método Commit (), hay datos en la base de datos.
Ejemplo de generación de claves primarias de manera nativa:
public class user1 {private entero uid; private string uname; private date birthday; public integer getuid () {return uid;} public void setuid (integer uid) {this.uid = uid;} public string getuname () {return une;} public void setuname (string uname) {this.uname = uname;} getBirthday () {) {) cumpleaños;} public void setBirthday (cita cumpleaños) {this.birthday = cumpleaños;}}User1.hbm.xml:
<? xml versión = "1.0"?> < paquete = "com.lixue.bean"> <!-El nombre del nodo de clase representa el nombre de clase de la entidad (recuerde modificar el nombre de clase al asignar el archivo de asignación, de lo contrario ocurrirá un error), la tabla representa el nombre de la entidad asignada a la tabla en la base de datos-> <nombre de clase = "user1" table = "t_user1"> <id name = "uid" <<<<<<< </id> <propiedad name = "uname"/> <propiedad name = "cumpleaños"/> </class> </hibernate-mapping>
Método de prueba:
/ ***Test Estrategia de generación de clave primaria nativa*/ public void testSave2 () {/*Sesión definida y cosas*/ session session = null; Transacción transacción = nulo; Pruebe { /*Get Session y Things* / Session = HibernateUtil.getSession (); transacción = session.beGinTransaction (); /*Crear usuario*/ user1 user = new User1 (); user.setUname ("Li Keqiang"); user.setBirthday (nueva fecha ()); / *** Debido a que la estrategia de generación de clave principal de User1 es nativa, después de llamar a session.save (), la instrucción Insertar se ejecutará y el objeto de recopilación temporal se borrará* Devolver el ID generado por la base de datos, incluida la administración de la sesión, y modificó el estado de Incentuencia de Existencia en la sesión en la sesión verdadera,* si el nivel de isolación de la isolación de la base de datos no se envía a la lectura, luego podemos ver el estado de la sesión*. transacción.commit (); } catch (Exception e) {E.PrintStackTrace (); transacción.rollback (); } finalmente {hibernateUtils.clossessession (sesión); }} Depurar el programa a través del punto de ruptura:
1. Dado que la estrategia de generación de clave principal es nativa, después de llamar al método save (), se ejecutará la instrucción Insertar y se borrarán los datos en el objeto de recopilación temporal, y se devolverá la ID generada por la base de datos.
2. Incluya el objeto en la gestión de la sesión, modifique la propiedad ExistSindAdatabase en PersistenceContext a True (indica que hay datos correspondientes en la base de datos, pero no se puede ver debido al área de aislamiento).
Probemos otro método de hibernación, que es desalojo (), lo que significa expulsar el objeto desde la sesión.
Para el programa que genera una estrategia de clave primaria UUID, aquí hay un método de prueba:
/ ***Pruebe la estrategia de generación de claves primarias de UUID*/ public void testSave3 () {/*Sesión definida y cosas*/ sesión Session = null; Transacción transacción = nulo; Pruebe { /*Get Session y Things* / Session = HibernateUtil.getSession (); transacción = session.beGinTransaction (); /*Crear usuario*/ usuario user = new User (); user.setUname ("Hu Jintao"); user.setBirthday (nueva fecha ()); /*** Debido a que la estrategia de generación de clave principal del usuario es UUID, después de llamar a Guardar, simplemente incorporar al usuario en la administración de sesión* no emitirá la instrucción Insertar, pero la ID se ha generado. El estado existsindateBase en la sesión es falso */ session.save (usuario); /*Desalojo El objeto de usuario de la sesión, es decir, expulsado de la propiedad EntityEntries de PersistenceContext*/ session.evict (usuario); /** * no puede enviar con éxito, porque cuando Hibernate limpia el caché, el objeto de usuario se elimina de la sesión inserta la colección temporal para insertar * Después de la operación, las existencias que indican en la propiedad EntityEntries se deben actualizar a verdadero, y llamamos el método malvado * el usuario de las entidades de entidad de la sesión, por lo que no se puede actualizar la propiedad de existencia, y no se puede encontrar una propiedad de existencias, y no se puede encontrar una excepción, y no se puede actualizar una excepción *, y no se puede actualizar una excepción *, y es actualizar una excepción *, y es actualizar una excepción. transacción.commit (); } catch (Exception e) {E.PrintStackTrace (); transacción.rollback (); } finalmente {hibernateUtils.clossessession (sesión); }} Depuración a través de puntos de interrupción:
1. Dado que se utiliza la estrategia de generación de clave principal de UUID, la instrucción Insertar no se enviará después de llamar al método Save (). El objeto está incluido en la gestión de la sesión. La ID se ha generado y no hay datos correspondientes en la base de datos (es decir, el valor del atributo ExistSindAdatabase es falso).
2. Después de llamar a Evict (), expulsar el objeto de usuario de la sesión, es decir, expulsado de la propiedad EntityEntries de PersistenceContext.
3. Cuando llamo al método Commit () nuevamente, encontraremos que nuestros datos no se pueden guardar porque al principio nuestra propiedad de existencia de Indatabase era falsa, es decir, no hay datos correspondientes en la base de datos. Luego llamamos a Evil () para eliminar todas las propiedades del objeto en PersistenceContext (también se incluye la propiedad de ExistenceIndatabase), pero los datos almacenados temporales en ActionQueue no se han eliminado. Cuando llamamos al método Commit (), primero llamaremos implícitamente el método FLUSH (). La función de este método también se ha mencionado anteriormente. Insertará el objeto temporal en ActionQueue, y luego establecerá el valor de la propiedad EXISTENDATABASE en el PersistenCeContext a verdadero. Desafortunadamente, no existe una propiedad de INTERSEDABASE en PersistenceContext, por lo que ocurrirá un error, lo que resulta en la incapacidad de guardar.
Para hacer esto, mejoramos el procedimiento anterior:
/ ***Pruebe la estrategia de generación de claves primarias de UUID*/ public void testSave4 () {/*Sesión definida y cosas*/ session session = null; Transacción transacción = nulo; Pruebe { /*Get Session y Things* / Session = HibernateUtil.getSession (); transacción = session.beGinTransaction (); /*Crear usuario*/ usuario user = new User (); user.setUname ("Hu Jintao"); user.setBirthday (nueva fecha ()); /*** Debido a que la estrategia de generación de clave principal del usuario es UUID, después de llamar a Guardar, simplemente incorporar al usuario en la administración de sesión* no emitirá la instrucción Insertar, pero la ID se ha generado. El estado de existencia deBase en persistenceContext es falso */ session.save (usuario); / ***Después de descargar, Hibernate limpiará el caché, guardará el objeto de usuario en la base de datos, borrará el objeto de usuario en las inserciones en la sesión*y establecerá el estado de ExistSindAdatabase en persistenceContext a true*/ session.flush (); / * Evice el objeto de usuario de la sesión, es decir, expulsado de la propiedad EntityEntries de persistenceContext */ session.evict (usuario); / *** se puede enviar correctamente porque Hibernate no puede estar en la recopilación de inserciones de sesión al limpiar el caché* Se encontró el objeto de usuario (borrado cuando se llamó a Flush), por lo que la instrucción de inserción no se emitirá, ni el estado de ExistSindatabase en la sesión no se actualizará*/ transacción.Commit (); } catch (Exception e) {E.PrintStackTrace (); transacción.rollback (); } finalmente {hibernateUtils.clossessession (sesión); }} NOTA: Después de guardar, llamamos al método FLUSH () y luego llamamos al método desaliente () después del programa modificado.
Depuración a través de puntos de interrupción:
1. Debido a que sigue siendo una estrategia de generación UUID, después de llamar a Save, la declaración de inserción no se emitirá, pero el objeto se incluirá en la gestión de la sesión. La propiedad ExistSindAdAtabase en PersistenceContext es falsa.
2. Después de llamar a Save (), volvemos a llamar al método FLUSH (). La función de este método es limpiar el caché, es decir, emitir una instrucción de inserción, insertar el objeto temporal en las inserciones en la sesión en la base de datos, luego borrar la colección temporal y establecer la propiedad existsIndAdatabase en la persistenciaContext en verdadero.
3. Después de llamar a FLUSH (), se llama al método Evict (). Su función es borrar el objeto de usuario de la sesión, es decir, borrar la propiedad EntityEntries de PersistenceContext.
4. Después de llamar al método SALVICT (), el método Commit () llamará implícitamente el método FLUSH () primero. La función de FLUSH es borrar el caché, es decir, inserte el objeto en la sesión de la sesión-> inserciones temporales en la base de datos, pero hemos llamado el método FLUSH () antes (nota: después de llamar a este método, la colección temporal se borrará), por lo que la colección temporal no tiene objetos en absoluto, por lo que la declaración de inserción no se emitirá. No actualizará el estado existsIndAdAbase en PersistenceContext. Enviar con éxito.
Consideremos el uso del método Evict () en la estrategia de generación de clave primaria nativa:
/ ***Test Estrategia de generación de clave primaria nativa*/ public void testSave5 () {/*Sesión definida y cosas*/ session session = null; Transacción transacción = nulo; Pruebe { /*Get Session y Things* / Session = HibernateUtil.getSession (); transacción = session.beGinTransaction (); /*Crear usuario*/ user1 user = new User1 (); user.setUname ("ma ying-jeou"); user.setBirthday (nueva fecha ()); / *** Debido a que la estrategia de generación de clave principal de User1 es nativa, después de llamar a session.save (), se ejecutará la instrucción Insertar,* Devuelve la identificación generada por la base de datos, incluida en la administración de la sesión, modifica el estado de existencia de Existencia en el estado de la sesión en la sesión verdadera, y borra el conjunto temporal* si el nivel de aislamiento de la base de datos se establece en no se envía a la lectura, luego podemos ver los datos salvados*/ Sess. /* Evice el objeto de usuario de la sesión, es decir, expulsado de la propiedad EntityEntries de PersistenceContext*/ session.evict (usuario); / *** se puede enviar correctamente porque Hibernate está en la recopilación de inserciones de sesión al limpiar la memoria caché* El objeto de usuario no se puede encontrar, por lo que no se emitirá la declaración de inserción, ni el estado de existIndatabase en la sesión no se actualizará*/ transaccion.commit (); } catch (Exception e) {E.PrintStackTrace (); transacción.rollback (); } finalmente {hibernateUtils.clossessession (sesión); }} A través de la depuración:
1. Dado que la estrategia de generación de clave principal es nativa, después de llamar al método Guardar, se emitirá una declaración de inserción de inmediato, devolviendo la ID generada por la base de datos, incorporando el objeto en la gestión de la sesión, modificando la propiedad de existencia Indatabase en PersistenceNtext a True, es decir, hay datos correspondientes en la dataBase y los objetos en la recopilación temporal se borrarán. Sin embargo, debido al nivel de aislamiento de MySQL, no podemos ver los datos antes de cometerlo.
2. Después de llamar a Save, se llama al objeto y el objeto se expulsa de la sesión, es decir, se expulsa de las entidades en el PersistenceContext.
3. Después de llamar al método desvict (), el método Commit () se puede llamar con éxito. La confirmación se puede guardar con éxito, porque antes de llamar a Commit (), el método FLUSH () se llamará implícitamente, es decir, limpiar el caché y buscar objetos en la colección temporal para insertar en la base de datos. Sin embargo, encontrará que no hay datos en la recopilación temporal, por lo que no se emitirá la declaración de inserción, y la propiedad de ExistenceIndatabase en PersistenceContext no se actualizará.
A través de los casos anteriores, podemos ver que a veces necesitamos llamar al método FLUSH () para limpiar el caché. Además, también encontramos un problema de lo anterior, es decir, cuando guardamos () los datos, no podemos ver los datos antes de enviarlos, es decir, el nivel de aislamiento de la base de datos es limitado. Ahora hablemos sobre el nivel de aislamiento de MySQL:
1. Verifique el nivel de aislamiento actual de la base de datos MySQL:
seleccionar @@ tx_isolation;
Nota: De la figura, podemos ver que el nivel de aislamiento predeterminado de la base de datos MySQL es repetible, lo que significa que no habrá una lectura no repetible, es decir, debe enviarse antes de que pueda leerse.
2. Modifique el nivel de aislamiento actual de MySQL (suponiendo que no se envíe para leer, es decir, se puede leer sin cometer):
set transaction isolation level read uncommited;
Lo anterior es toda la explicación detallada del código de nivel de sesión y nivel de aislamiento de Hibernate. 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!