Análisis del principio de mybatis (cuatro) proceso de consulta

El análisis principal de los tres primeros Mybatis se puede ver haciendo clic en el enlace:

Análisis del principio de Mybatis (1) analizar el archivo de configuración xml global para generar el proceso SqlSessionFactory

Análisis del principio de Mybatis (dos) el proceso de creación de SqlSession

Análisis del principio de Mybatis (tres) -getMapper obtiene dinámicamente la clase de implementación de la interfaz

Este artículo habla principalmente del proceso de consulta de Mybatis basado en los tres primeros artículos (igual que agregar, eliminar y modificar), y también es el conocimiento central en Mybatis, no diré mucho, pero depurar es respetuoso.

Dijimos en el tercer artículo que el objeto de interfaz Mapper que obtenemos es en realidad una clase de implementación de proxy, el proxy es el objeto MapperProxy y el objeto MapperProxy no implementa nuestra interfaz Mapper, por lo que cuando llamamos al método de interfaz de la clase proxy , El método de invocación dará una condición para juzgar si es un método de la clase Object (si no hay tal juicio aquí, el programa reportará un error, vea la explicación en el Capítulo 3 para más detalles), es obvio que estamos llamando al método de interfaz, no al método Object , Entonces nuestro programa viene directamente al método cachedMapperMethod, en profundidad este método

 En realidad, aquí hay una optimización, a través de un contenedor de mapas para almacenar en caché nuestro MapperMethed, la clave es el método de interfaz llamado Método y el valor es MapperMethod. Hay dos atributos principales en este MapperMethod:

Uno de los objetos SqlCommand, luego echemos un vistazo a lo que hay en este SqlCommand y veamos su constructor.

En primer lugar, es una clase interna de MapperMethod. Hay dos atributos en él, a saber, nombre y tipo. Luego, te diré la función de estos dos atributos directamente. El atributo de nombre obtiene lo que llamamos de acuerdo con la interfaz y el método pasados. El nombre de la ruta completa del método va a Configuración para obtener el MappedStatement correspondiente, y luego asigna el id del objeto MappedStatement al nombre, y el tipo es el mismo, que también se obtiene asignando el sqlCommandType del MappedStatement. El otro MethodSignature también es una clase interna de MapperMethod. Su función es determinar qué tipo de método de interfaz se devuelve la llamada. No hablaré de eso aquí.

Las dos clases mencionadas anteriormente en realidad están sentando las bases para lo siguiente, hacemos clic en Siguiente, llegamos al método mapperMethod.execute y continuamos en profundidad.

Se puede ver que lo primero aquí es juzgar el tipo de método por el tipo de SqlCommand en MapperMethod. Como somos un método de consulta aquí, hemos llegado a la rama SELECT.

En la rama SELECT, el valor de retorno del método se juzga nuevamente, y es diferente si las ramas se toman de acuerdo con el valor de retorno del método. Obviamente, el juicio condicional aquí es el crédito de MethodSignature que mencionamos anteriormente. Luego vino el método sqlSession.selectOne, pasó el nombre de ruta completo del método y los parámetros del método de interfaz que se llamará, y continuó profundizando.

 Sumérjase en el método selectList.

Ve más profundo.

 Se puede ver que de acuerdo con el valor de nombre del sqlCommond anterior, se obtiene el objeto MappedStatement correspondiente en el objeto Configuration, y luego se llama al método ejecutor.query. Note que hay un método wrapCollection. A partir del nombre, podemos ver que debería estar ajustado para nuestro objeto parámetro. No hay mucho aquí. Luego continúe profundizando en el método de consulta.

El objeto BoundSql se puede obtener mediante el método getBoundSql del MappedStatement entrante, que contiene nuestra declaración SQL original. Y CacheKey es un valor clave utilizado para nuestra caché secundaria, continúe profundizando en el método de consulta a continuación.

 El método de consulta de CachingExecutor se llama aquí, porque hemos configurado el caché de segundo nivel por defecto, por lo que el Executor que realmente ejecutamos será empaquetado por CachingExcutor, aquí hablamos de ello en la segunda parte, por lo que no entraremos en detalles. Entonces, si no hay datos en nuestra caché secundaria, debemos llamar a nuestro ejecutor real. Profundice en el método delegate.query.

Esto es similar a la caché de segundo nivel, primero se obtiene de la caché local, es decir, la caché de primer nivel, por lo que aquí podemos saber que el orden de la fuente de datos en Mybatis es la caché de segundo nivel primero, luego la caché de primer nivel y finalmente la base de datos. Nos sumergimos en el método queryFromDataBase. 

Método doQuery en profundidad

 En este momento, llegué al método doQuery de SimpleExecutor. Vi que primero obtuve el objeto Configuration del objeto MappedStatement entrante y luego llamé al método newStatementHandler de la configuración. Este método devolvió un objeto StatementHandler y profundizó en este método.

Puede ver que primero se creó un objeto RoutingStatemnetHandler a través de la subclase. ¿Qué es este objeto RoutingStatemnetHandler? Echemos un vistazo a su método de construcción.

En sus propiedades, hay un objeto de propiedad StatementHandler. De hecho, este objeto de propiedad es el objeto de ejecución real del método de esta clase. Es decir, RoutingStatementHandler es en realidad una capa de empaquetado, y la creación de este objeto se basa en nuestro archivo de configuración Para determinar el statementType establecido, el valor predeterminado es crear un PrepareStatementHandler precompilado.

Luego mire el código interceptorChain.pluginAll (statementHandler) en el cuadro rojo de arriba . Es un código muy familiar. De hecho, este código apareció cuando inicializamos el Ejecutor. También veremos este código en el siguiente código. Relacionado con el mecanismo de complementos de Mybatis. Entonces, ¿qué es este objeto StatementHandler? Primero ejecutemos el siguiente código.

Después de ejecutar el método newStatementHandler, vine al método prepareStatement a continuación para profundizar en este método.

Puede verse que, de hecho, nuestro objeto StatementHandler se usa para obtener el objeto Statement, y este objeto Statement es el objeto Statement en el jdk cuando estamos aprendiendo la programación JDBC, por lo que la operación de la base de datos por Mybatis encapsula JDBC. Echemos un vistazo a cómo el StatementHandler obtiene el Statement y vayamos a handler.prepare

Puede ver que se llama al método prepare de prepareStatement, y este método se usa en profundidad.

 Puede ver aquí que obtiene la declaración sql de boundSql y luego llama al método connection.prepareStatement para pasar el sql, por lo que obtiene el objeto Statement.

Luego vino handler.parameterize (stmt), y luego entramos y echamos un vistazo.

El método setParameters de parameterHandler se llama dentro, y ¿qué es este objeto parameterHandler? Regresemos a inicializar PreparedStatementHandler antes.

No existe tal objeto parameterHandler en PreparedStatementHandler, y PreparedStatementHandler se hereda de BaseStatementHandler, por lo que el objeto parameterHandler de inicialización debe estar en el método de construcción de su clase padre BaseStatementHandler.

Vaya al método de construcción de BaseStatementHandler, profundice en el método configuration.newParameterHandler.

Se puede ver que tanto newParameterHandler como newResultSetHandler tienen un mecanismo para llamar al complemento Mybatis. En la actualidad, sabemos que los cuatro objetos que pueden ser interceptados por el complemento Mybatis son Executor, StatementHandler, ParameterHandler y ResultSetHandler . De hecho , estos cuatro objetos pueden ser interceptados por el complemento Mybatis. En Mybatis, estamos acostumbrados a llamar a esto Mybatis Cuatro componentes principales.

Supongo que te gusta

Origin blog.csdn.net/weixin_37689658/article/details/99617925
Recomendado
Clasificación