Entender los principios subyacentes serie de análisis artículo mybatis

Consejos: El objetivo de este artículo es mybatis resueltos realizan un proceso de SQL, el proceso de comparación pensamiento saltar, relativamente rara que se puede ver un resumen de fuente fluya hacia abajo


 

El artículo para resolver mybatis realizar un SQL a través de un proceso de ejecución de la instrucción de inserción. Fondo, de la fuente mybatis-3.0.5.jar,

SqlMapConfig.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC 
	"-//mybatis.org//DTD Config 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

	<properties resource="jdbc.properties" />
	<!-- 配置别名 -->
	<typeAliases>
		<typeAlias type="dao.DataDao" alias="DataDao" />
	</typeAliases>
	 
	<!-- 配置环境变量 -->
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="${driverClass}" />
				<property name="url" value="${jdbcUrl}" />
				<property name="username" value="${DBusername}" />
				<property name="password" value="${DBpassword}" />
			</dataSource>
		</environment>
	</environments>
	
	<!-- 配置mappers -->
	<mappers>

		<mapper resource="dao/DataDao.xml" />
	</mappers>
	
</configuration>   

Mapper interfaz correspondiente:

public interface DataDao {

    public  int mysqlInsert(Map<String, Object> map) throws Exception;
}

Correspondiente a la interfaz de DataDao.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao.DataDao">
   <insert id="mysqlInsert" parameterType="map" >
		insert into ${tableName}
		(${columns})
		values
		(${colValues})
	</insert>
</mapper>

En primer lugar, vamos a venir a interpretar la entrada desde donde mybatis cargado, busca una mybatis Introduce el código:

/**
     * 传入map参数,执行插入
     * @param map
     * @return
     */
    public static int mysqlInsert(Map<String, Object> map) throws Exception {
        SqlSession session = null;
        int index=0;
        try {
            session = SessionFactory.getSession();
            DataDao dataDao = session.getMapper(DataDao.class);
            index=dataDao.mysqlInsert(map);
            if(index>0){
                logger.info("insert success: "+index);
            }
             session.commit(true);
        } catch (Exception e) {
            logger.error("插入异常:", e);
            session.rollback(true);
            throw e;
        } finally {
            session.close();
        }
        return index;
    }
public class SessionFactory {

    private static Logger logger =  LoggerFactory.getLogger(SessionFactory.class);

    private static SqlSessionFactoryBuilder sqlSessionFactoryBuilder;
    private static SqlSessionFactory sqlSessionFactory;

        //初始化mybatis
        static {
            String resource = "mybatis-config.xml";
            Reader reader = null;
            try {
                reader = Resources.getResourceAsReader(resource);
                sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
                sqlSessionFactory = sqlSessionFactoryBuilder.build(reader);
            } catch (IOException e) {
                logger.error("加载配置文件错误:",e);
                e.printStackTrace();
            }catch (Exception e){
                logger.error("加载配置文件错误:",e);
            }

            logger.info("init mybatis");
        }

    public  static synchronized SqlSession getSession() throws IOException {
        SqlSession sqlSession =null;
        if(null == sqlSession) {
            sqlSession = (null != sqlSessionFactory)?sqlSessionFactory.openSession(): null;
        }
        return sqlSession;
    }

}

Puede ver el código irá primero a través de obtener SqlSession SessionFactory, que habrá un código estático cuando el cargador de clases SessionFactory llevará a cabo el proceso de inicialización SqlMapConfig.xml. Ahora miramos directamente centramos en: 

DataDao interfaz de adquisición de datos a través del tiempo SqlSession getMapper encontró dos fechas Aplicación volver a la inicialización SessionFactory verá el siguiente párrafo:

Así que nos vamos directamente al método DefaultSqlSession getMapper se pueden encontrar en MapperRegistry:

Vea aquí los amigos familiares dinámicas proxies saben que esto está escrito en Java para obtener una clase dinámica proxy (ps: no está familiarizado con el proxy dinámico, se puede ver aquí mi último blog  proxy dinámico vernácula resuelto ), seguimos mirando hacia abajo :

Continuar para pasar al siguiente paso: dataDao.mysqlInsert (mapa); MapperProxy llama método invoke de llevar a cabo este método:

Además del método objeto de código abierto ver la agencia no puede, la otra vendrá mapperMethod.execute (args):

campo de tipo será evaluado cuando mapperMethod inicialización, en el que realizar operaciones de inserción, actualización método DefaultSqlSession seguirán disminuyendo:

Después de aquí, entonces comenzamos a ver la inicialización de configuración, configuración cuando es inicializado SqlSessionFactory

Lo anterior se puede ver de configuración 2 del código se inicializa por la carga SqlMapConfig.xml.

Ahora volvemos a this.configuration.getMappedStatement (declaración); este código:

Ir a buscar encontramos que él es, de hecho, para obtener el correspondiente MappedStatement por id, por lo anterior podemos ver número se pasa en el MapperMethod método de ejecución de la CommandName, que setupFields método en el constructor para inicializar MapperMethod en:

Valores en el presente documento: DataDao.mysqlInsert. Como éste, que es la interfaz nombre de método de clase.

Ahora volvemos a la corriente principal, vemos mappedStatements proceso de inicialización es this.mapperElement (root.evalNode ( "mapeadores")) en la inicialización de configuración anterior; en: 

Aquí análisis sintácticos sql mapper.xml nodo en la sección de ejemplos de este artículo es:

Seguimos considerando que los mappedStatements de inicialización:

Identificación Aquí podemos ver que el valor de namespace.id de empalme de nodos, que es DataDao.mysqlInsert

 

Ahora seguimos para volver al flujo principal, mira este código:

Actualización de la ejecución de código método por el ejecutor, y ahora nos fijamos ejecutor del proceso de inicialización es un proceso en el SqlSession inicialización:

En el constructor de configuración se puede ver aquí por defecto executorType es simple, por defecto cacheEnabled es cierto.

Ahora seguimos para volver al flujo principal, en el método de actualización en CachingExecutor:

Aquí entra en el método de actualización BaseExecutor

Aquí vamos a entrar en SimpleExecutor de doUpdate en:

Aquí primera inicializa una RoutingStatementHandler, evidente de lo anterior por defecto StatementType preparado, por lo que la propiedad delegado de PreparedStatementHandler. Volvimos al flujo principal, seguimos buscando this.prepareStatement (manejador):

Vendré para preparar el método BaseStatementHandler: 

Aquí vamos a entrar en instantiateStatement método PreparedStatementHandler de:

boundSql aquí es que cuando en la anterior inicialización mappedStatement de asignación:

 

El primero se inicializa en parseStatementNode DynamicSqlSource, a continuación, obtener BoundSql, a continuación, nos fijamos parseDynamicTags método XMLStatementBuilder de:

Podemos ver si el código no es ni un tipo de nodo nodo de texto no es CDATA nodo será llamado para hacer frente a un tipo diferente de tratamiento, que más comúnmente utilizado es el <Si> y <donde> nodos utilizados en la consulta, donde llevamos a cabo es inserto, es un nodo de texto directamente, la siguiente es la inicialización y configuración de un MixedSqlNode construido DynamicSqlSource, a continuación, construido por el método getBoundSql BoundSql:

 De lo anterior conocida: rootSqlNode es MixedSqlNode, Este método realiza la aplican MixedSqlNode, en las presentes realiza realización el TextSqlNode aplican

métodos:

Esta sección se utiliza principalmente para procesarlo en el parámetro marcador de posición sql $ {}, en el presente documento el inserto en $ {} nombreTabla ($ {columnas}) valores ($ {colValues}) después de la inserción de análisis sintáctico de conversión en la tabla (id , valores de nombre) (1, 'test'), esta sección de código es no analizados, relativamente complicada, principalmente a través del marcador de posición correspondiente se sustituye con el valor correspondiente.

Volvemos al método getBoundSql, continuará a bajar, a sqlSourceParser.parse (context.getSql (), parameterType) esta línea de código: 

Vi código familiar, que es una sección #} {marcador de posición se reemplaza con un valor correspondiente.

Continuamos para volver al flujo principal instantiateStatement método PreparedStatementHandler arriba, y bajar:

Jdbc3KeyGenerator aquí es que si se establece useGeneratedKeys = true clave principal se utiliza para generar de forma automática, de acuerdo con la presente realización es tampoco resultSetType relaciona vacío, por lo que habrá un retorno a la PreparedStatement, aquí doUpdate de nuestra SimpleExecutor this.prepareStatement (manejador)

Este análisis de código terminado.

Volvemos al flujo principal continuará a bajar:

Aquí el proceso procede a ejecutar la PreparedStatement JDBC realiza la inserción de las operaciones de inserción. 2 del código detrás no analizados, utilizados principalmente para obtener la clave principal.

Aquí, mybatis realizan un mecanismo de operación de SQL de inserción en el análisis se ha completado.

 

resumen:

 En el proceso de análisis de código fuente, puede ser más salto, ya que habrá alguna clase de ejecución de inicialización o clase de configuración en proceso de análisis de código fuente. Aquí para compartir el código fuente para leer de forma rápida para ver el código fuente en el proceso, puede haber muchas extensiones, calibración, el código de inicialización para algunas funciones, tales como:

   1. Configuración de clase de inicialización

   2. Realizar interceptor interceptor (en realidad utiliza una cadena de patrones de diseño de responsabilidad y los patrones de diseño para lograr proxies dinámicos de intercepción)

   3. caché caché implementaciones

Puede omitir temporalmente, ir primero sobre el flujo principal del código, tales como mybatis realizar un proceso de SQL puede ver el código fuente como sigue:

 

Cuando vemos todo el proceso para lograr claro, si desea ver más detalles, puede usar la otra vez para ver la ejecución posterior de la funcionalidad ampliada

Publicado 25 artículos originales · ganado elogios 51 · Vistas a 20000 +

Supongo que te gusta

Origin blog.csdn.net/Royal_lr/article/details/88883890
Recomendado
Clasificación