tft每日頭條

 > 科技

 > mybatis 參數綁定

mybatis 參數綁定

科技 更新时间:2024-06-16 22:14:45
1.StatementHandler中通過ParemeterHandler給Statement設置參數

Mybatis中SqlSession執行Sql語句過程中,實際上是通過Executor來執行Sql

Executor執行Sql的方法中,又是通過StatementHandler來實現

Executor中首先會創建StatementHandler對象,如果創建的是PrepareStatementHandler和CallableStatementHandler,在創建了對應的Statement之後,會使用ParemeterHandler給Statement設置參數

mybatis 參數綁定(Mybatis參數-ParameterHandler設置參數)1

2.configuration中創建ParameterMapping

首先看下ParameterHandler的初始化過程,ParameterHandler是StatementHandler的一個屬性,在構造方法中進行初始化

初始化方法是通過Configuration的newParameterHandler方法實現

public abstract class BaseStatementHandler implements StatementHandler { protected final ParameterHandler parameterHandler; protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { ... this.parameterHandler = this.configuration.newParameterHandler(mappedStatement, parameterObject, boundSql); } ... }

Configuration的newParameterHandler方法中,通過mappedStatement來創建ParameterHandler對象

創建了StatementHandler對象後,會調用interceptorChain的pluginAll方法來處理StatementHandler對象,最後強轉為StatementHandler類型

InterceptorChain中保存了Interceptor的集合,如果配置了Interceptor,那麼Interceptor會對StatementHandler對象進行動态代理,擴展StatementHandler的方法

public class Configuration { protected final Map<String, MappedStatement> mappedStatements; public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) { ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql); parameterHandler = (ParameterHandler)this.interceptorChain.pluginAll(parameterHandler); return parameterHandler; } ... }

MappedStatement的getLang方法返回LanguageDriver對象,然後調用LanguageDriver的createParameterHandler方法創建ParameterHandler

LanguageDriver的默認實現是XMLLanguageDriver,XMLLanguageDriver中創建了一個DefaultParameterHandler對象

public class XMLLanguageDriver implements LanguageDriver { public ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) { return new DefaultParameterHandler(mappedStatement, parameterObject, boundSql); } ... }

3.ParameterHandler實例化

ParameterHandler是一個接口,其實現類是DefaultParameterHandler

mybatis 參數綁定(Mybatis參數-ParameterHandler設置參數)2

DefaultParameterHandler的構造方法中對其屬性進行賦值

public class DefaultParameterHandler implements ParameterHandler { private final TypeHandlerRegistry typeHandlerRegistry; private final MappedStatement mappedStatement; private final Object parameterObject; private final BoundSql boundSql; private final Configuration configuration; public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) { this.mappedStatement = mappedStatement; this.configuration = mappedStatement.getConfiguration(); this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry(); this.parameterObject = parameterObject; this.boundSql = boundSql; } ... }

4.ParameterHandler給PrepareStatement傳遞參數

了解了ParameterHandler的初始化過程之後,繼續查看ParameterHandler給PrepareStatement設置參數過程

在setParameters方法中會遍曆ParameterMapping,并根據屬性名在ParameterMapping中獲得值和TypeHandler,然後通過TypeHandler來給PrepareStatement設置參數

public class DefaultParameterHandler implements ParameterHandler { ... public void setParameters(PreparedStatement ps) { ErrorContext.instance().activity("setting parameters").object(this.mappedStatement.getParameterMap().getId()); //從BoundSql中獲得參數映射 List<ParameterMapping> parameterMappings = this.boundSql.getParameterMappings(); if (parameterMappings != null) { //遍曆parameterMappings for(int i = 0; i < parameterMappings.size(); i) { ParameterMapping parameterMapping = (ParameterMapping)parameterMappings.get(i); //ParameterMode類型不為OUT if (parameterMapping.getMode() != ParameterMode.OUT) { //根據名稱獲得參數值 String propertyName = parameterMapping.getProperty(); Object value; if (this.boundSql.hasAdditionalParameter(propertyName)) { value = this.boundSql.getAdditionalParameter(propertyName); } else if (this.parameterObject == null) { value = null; } else if (this.typeHandlerRegistry.hasTypeHandler(this.parameterObject.getClass())) { value = this.parameterObject; } else { MetaObject metaObject = this.configuration.newMetaObject(this.parameterObject); value = metaObject.getValue(propertyName); } //parameterMapping獲取TypeHandler和JdbcType TypeHandler typeHandler = parameterMapping.getTypeHandler(); JdbcType jdbcType = parameterMapping.getJdbcType(); if (value == null && jdbcType == null) { jdbcType = this.configuration.getJdbcTypeForNull(); } try { //通過TypeHandler給PrepareStatement設置參數 typeHandler.setParameter(ps, i 1, value, jdbcType); } catch (SQLException | TypeException var10) { throw new TypeException("Could not set parameters for mapping: " parameterMapping ". Cause: " var10, var10); } } } } } }

5.TypeHandler設置參數

這裡簡單看下StringTypeHandler的設置方法,StringTypeHandler繼承BaseTypeHandler類

BaseTypeHandler類的setParameter方法中,如果隻不為null,則會調用setNonNullParameter方法,StringTypeHandler中實現了該方法,方法中直接使用下标的方式給PrepareStatement設置String類型的參數

mybatis 參數綁定(Mybatis參數-ParameterHandler設置參數)3

public class StringTypeHandler extends BaseTypeHandler<String> { public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, parameter); } ... }

6.總結

如果Mybatis中使用的是PrepareStatement,則會使用ParameterHandler給PrepareStatement設置參數,設置參數時,會根據MappedStatement的類型來選擇對應的TypeHandler。在TypeHandler中直接通過下标方式給PrepareStatement設置參數

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved