jmeter中如何獲取上一個接口返回值,MyBatis3源碼解析(6)TypeHandler使用

 2023-10-12 阅读 28 评论 0

摘要:簡介 在上幾篇中,介紹了MyBatis3對參數和結果的解析轉換,對于常規數據類型,默認的處理已經足夠應付了,但日常開發中會有一些特殊的類型,就可以通過TypeHandler來進行處理 示例準備 本篇文中用于調試的測試代碼請參考:MyBatis3源碼解

簡介

在上幾篇中,介紹了MyBatis3對參數和結果的解析轉換,對于常規數據類型,默認的處理已經足夠應付了,但日常開發中會有一些特殊的類型,就可以通過TypeHandler來進行處理

示例準備

本篇文中用于調試的測試代碼請參考:MyBatis3源碼解析(1)探索準備

完整的工程已放到GitHub上:https://github.com/lw1243925457/MybatisDemo/tree/master/example

jmeter中如何獲取上一個接口返回值、熟悉使用的可以跳過該部分,直接到源碼解析部分

數據模型修改

我們先將原來的String類型變成String數組,存入數據庫時,使用逗號進行分割,取出時轉成String數組,即

  • Java數據結構:
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {private Long id;private String[] name;
}
  • 存入數據庫,已Varchar的方式:1,2,3

自定義TypeHandler編寫

我們修改完數據結構后,需要編寫一個自定義的TypeHandler,如下:

public class StringArrayTypeHandler extends BaseTypeHandler<String[]> {@Overridepublic void setNonNullParameter(PreparedStatement preparedStatement, int i, String[] strings, JdbcType jdbcType)throws SQLException {preparedStatement.setString(i, StringUtils.join(strings, ","));}@Overridepublic String[] getNullableResult(ResultSet resultSet, String s) throws SQLException {return convert(resultSet.getString(s));}@Overridepublic String[] getNullableResult(ResultSet resultSet, int i) throws SQLException {return convert(resultSet.getString(i));}@Overridepublic String[] getNullableResult(CallableStatement callableStatement, int i) throws SQLException {return convert(callableStatement.getString(i));}/*** 將查詢值轉換為數組** @param value 查詢值, String* @return 轉換結果, String[]*/private String[] convert(String value) {return StringUtils.isEmpty(value) ? new String[0] : value.split(",");}
}

TypeHandler注冊

將我們自定義的TypeHandler進行注冊,MyBatis后將對應String【】和Varchar使用此TypeHandler

public class MybatisTest {public static SqlSessionFactory buildSqlSessionFactory() {......Configuration configuration = new Configuration(environment);// 注冊TypeHandler,注意需要在添加Mapper之前,因為添加Mapper操作的時候就需要TypeHandler了configuration.getTypeHandlerRegistry().register(String[].class, JdbcType.VARCHAR, StringArrayTypeHandler.class);configuration.addMapper(PersonMapper.class);SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();return builder.build(configuration);}
}

運行

java.lang.illegalaccesserror?測試結果如下:

Connected to the target VM, address: '127.0.0.1:53557', transport: 'socket'
[Person(id=1, name=[1, 2]), Person(id=2, name=[1, 2])]
Disconnected from the target VM, address: '127.0.0.1:53557', transport: 'socket'

源碼解析

參數解析設置

通過前面幾篇文章的分析,我們得到設置參數的相關源碼如下:

public class DefaultParameterHandler implements ParameterHandler {@Overridepublic void setParameters(PreparedStatement ps) {ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();if (parameterMappings != null) {for (int i = 0; i < parameterMappings.size(); i++) {ParameterMapping parameterMapping = parameterMappings.get(i);if (parameterMapping.getMode() != ParameterMode.OUT) {Object value;String propertyName = parameterMapping.getProperty();if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional paramsvalue = boundSql.getAdditionalParameter(propertyName);} else if (parameterObject == null) {value = null;} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {value = parameterObject;} else {MetaObject metaObject = configuration.newMetaObject(parameterObject);value = metaObject.getValue(propertyName);}// 獲取對應的TypeHandlerTypeHandler typeHandler = parameterMapping.getTypeHandler();JdbcType jdbcType = parameterMapping.getJdbcType();if (value == null && jdbcType == null) {jdbcType = configuration.getJdbcTypeForNull();}try {// 調動對應的方法,設置值typeHandler.setParameter(ps, i + 1, value, jdbcType);} catch (TypeException | SQLException e) {throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);}}}}}
}

設置值,函數如下:

public abstract class BaseTypeHandler<T> extends TypeReference<T> implements TypeHandler<T> {@Overridepublic void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {if (parameter == null) {if (jdbcType == null) {throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");}try {ps.setNull(i, jdbcType.TYPE_CODE);} catch (SQLException e) {throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . "+ "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. "+ "Cause: " + e, e);}} else {try {// 調用我們自定義的TypeHandler函數setNonNullParameter(ps, i, parameter, jdbcType);} catch (Exception e) {throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . "+ "Try setting a different JdbcType for this parameter or a different configuration property. "+ "Cause: " + e, e);}}}
}

如上所示,我們看到TypeHandler調用的大致流程

二次解析源碼,其中MyBatis3是根據Java Type 和 JDBC Type 來對應調用不同的TypeHandler的,在示例代碼中我們也顯式的注冊了 String數組和Varchar

這里使用的是一個全局的,也可以單獨在查詢中使用,可以自行搜索

結果解析返回

通過之前的文章,我們知道代碼如下:

  private Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix)throws SQLException {if (propertyMapping.getNestedQueryId() != null) {return getNestedQueryMappingValue(rs, metaResultObject, propertyMapping, lazyLoader, columnPrefix);} else if (propertyMapping.getResultSet() != null) {addPendingChildRelation(rs, metaResultObject, propertyMapping);   // TODO is that OK?return DEFERRED;} else {// 得到對應的TypeHandler,直接返回處理結果final TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);return typeHandler.getResult(rs, column);}}

GetResult函數如下,后面調用我們自定義的TypeHandler方法

  @Overridepublic T getResult(ResultSet rs, String columnName) throws SQLException {try {return getNullableResult(rs, columnName);} catch (Exception e) {throw new ResultMapException("Error attempting to get column '" + columnName + "' from result set.  Cause: " + e, e);}}

總結

php視頻解析源碼。本篇文章,展示了如何定義TypeHandler和使用TypeHandler,并展示了源碼部分,TypeHandler是如何對應生效的,了解該部分,在日常開發中,使用TypeHandler也能做到心中有數

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/135532.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息