当前位置: 首页 > news >正文

mybatis类型转换器

文章目录

    • TypeHandler
      • BaseTypeHandler
    • TypeHandlerRegistry
      • 属性
      • 无参构造
      • 有参构造
        • 以register(Boolean.class, new BooleanTypeHandler())为例
        • 以register(JdbcType.BOOLEAN, new BooleanTypeHandler());为例
      • UnknowTypeHandler

TypeHandler

public interface TypeHandler<T> {void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;T getResult(ResultSet rs, String columnName) throws SQLException;T getResult(ResultSet rs, int columnIndex) throws SQLException;T getResult(CallableStatement cs, int columnIndex) throws SQLException;}

BaseTypeHandler

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 {// 设置参数为null, 需要设定jdbcTypeps.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 {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);}}}@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);}}@Overridepublic T getResult(ResultSet rs, int columnIndex) throws SQLException {try {return getNullableResult(rs, columnIndex);} catch (Exception e) {throw new ResultMapException("Error attempting to get column #" + columnIndex + " from result set.  Cause: " + e, e);}}@Overridepublic T getResult(CallableStatement cs, int columnIndex) throws SQLException {try {return getNullableResult(cs, columnIndex);} catch (Exception e) {throw new ResultMapException("Error attempting to get column #"+ columnIndex + " from callable statement.  Cause: " + e, e);}}public abstract void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;public abstract T getNullableResult(ResultSet rs, String columnName) throws SQLException;public abstract T getNullableResult(ResultSet rs, int columnIndex) throws SQLException;public abstract T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException;}

TypeHandlerRegistry

属性

// 表示 JdbcType 对应 TypeHandler<?>
// JdbcType 一共有41个枚举值, 对应数据库中不同的数据类型
private final Map<JdbcType, TypeHandler<?>>  jdbcTypeHandlerMap = new EnumMap<>(JdbcType.class);// 表示 javaType 对应 Map<JdbcType, TypeHandler<?>>
// 其中 Map<JdbcType, TypeHandler<?>> 它的key可以是null,key为null也就是未指定jdbcType时的取值
private final Map<Type, Map<JdbcType, TypeHandler<?>>> typeHandlerMap = new ConcurrentHashMap<>();// 默认就初始化为 new UnknownTypeHandler(configuration)
private final TypeHandler<Object> unknownTypeHandler;// 表示 javaType 对应 TypeHandler<?>
private final Map<Class<?>, TypeHandler<?>> allTypeHandlersMap = new HashMap<>();// 没有值 的 Map<JdbcType, TypeHandler<?>>
private static final Map<JdbcType, TypeHandler<?>> NULL_TYPE_HANDLER_MAP = Collections.emptyMap();// 默认的枚举类型处理器
private Class<? extends TypeHandler> defaultEnumTypeHandler = EnumTypeHandler.class;

无参构造

public TypeHandlerRegistry() {this(new Configuration());
}

有参构造

这里面初始化了许多的TypeHandler到TypeHandlerRegistry

public TypeHandlerRegistry(Configuration configuration) {// 创建 UnknownTypeHandlerthis.unknownTypeHandler = new UnknownTypeHandler(configuration);// 注册针对 Boolean.class类型的 BooleanTypeHandler// 1、首先会去拿 BooleanTypeHandler 类上的@MappedJdbcTypes注解//    (mybatis包中提供的TypeHandler实现类都没有使用@MappedJdbcTypes注解)// 2、如果 TypeHandler实现类上没有 该注解,//    则注册 Boolean.class -> (null, booleanTypeHandler) 到 typeHandlerMap 中;//    如果有该注解,则注册 Boolean.class ->(注解的所有值,booleanTypeHandler) 到 typeHandlerMap 中;// 3、再注册 BooleanTypeHandler.class -> booleanTypeHandler 到 allTypeHandlersMap 中register(Boolean.class, new BooleanTypeHandler());register(boolean.class, new BooleanTypeHandler());// 注册 JdbcType.BOOLEAN -> booleanTypeHandler 到 jdbcTypeHandlerMap 中register(JdbcType.BOOLEAN, new BooleanTypeHandler());register(JdbcType.BIT, new BooleanTypeHandler());register(Byte.class, new ByteTypeHandler());register(byte.class, new ByteTypeHandler());register(JdbcType.TINYINT, new ByteTypeHandler());register(Short.class, new ShortTypeHandler());register(short.class, new ShortTypeHandler());register(JdbcType.SMALLINT, new ShortTypeHandler());register(Integer.class, new IntegerTypeHandler());register(int.class, new IntegerTypeHandler());register(JdbcType.INTEGER, new IntegerTypeHandler());register(Long.class, new LongTypeHandler());register(long.class, new LongTypeHandler());register(Float.class, new FloatTypeHandler());register(float.class, new FloatTypeHandler());register(JdbcType.FLOAT, new FloatTypeHandler());register(Double.class, new DoubleTypeHandler());register(double.class, new DoubleTypeHandler());register(JdbcType.DOUBLE, new DoubleTypeHandler());register(Reader.class, new ClobReaderTypeHandler());register(String.class, new StringTypeHandler());// 注册 String.class -> (JdbcType.CHAR, stringTypeHandler) 到 typeHandlerMap 中// 同时注册 String.class -> stringTypeHandler 到 allTypeHandlersMap 中register(String.class, JdbcType.CHAR, new StringTypeHandler());register(String.class, JdbcType.CLOB, new ClobTypeHandler());register(String.class, JdbcType.VARCHAR, new StringTypeHandler());register(String.class, JdbcType.LONGVARCHAR, new StringTypeHandler());register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler());register(String.class, JdbcType.NCHAR, new NStringTypeHandler());register(String.class, JdbcType.NCLOB, new NClobTypeHandler());register(JdbcType.CHAR, new StringTypeHandler());register(JdbcType.VARCHAR, new StringTypeHandler());register(JdbcType.CLOB, new ClobTypeHandler());register(JdbcType.LONGVARCHAR, new StringTypeHandler());register(JdbcType.NVARCHAR, new NStringTypeHandler());register(JdbcType.NCHAR, new NStringTypeHandler());register(JdbcType.NCLOB, new NClobTypeHandler());register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());register(JdbcType.ARRAY, new ArrayTypeHandler());register(BigInteger.class, new BigIntegerTypeHandler());register(JdbcType.BIGINT, new LongTypeHandler());register(BigDecimal.class, new BigDecimalTypeHandler());register(JdbcType.REAL, new BigDecimalTypeHandler());register(JdbcType.DECIMAL, new BigDecimalTypeHandler());register(JdbcType.NUMERIC, new BigDecimalTypeHandler());register(InputStream.class, new BlobInputStreamTypeHandler());register(Byte[].class, new ByteObjectArrayTypeHandler());register(Byte[].class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler());register(Byte[].class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler());register(byte[].class, new ByteArrayTypeHandler());register(byte[].class, JdbcType.BLOB, new BlobTypeHandler());register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler());register(JdbcType.LONGVARBINARY, new BlobTypeHandler());register(JdbcType.BLOB, new BlobTypeHandler());register(Object.class, unknownTypeHandler);register(Object.class, JdbcType.OTHER, unknownTypeHandler);register(JdbcType.OTHER, unknownTypeHandler);register(Date.class, new DateTypeHandler());register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());register(JdbcType.TIMESTAMP, new DateTypeHandler());register(JdbcType.DATE, new DateOnlyTypeHandler());register(JdbcType.TIME, new TimeOnlyTypeHandler());register(java.sql.Date.class, new SqlDateTypeHandler());register(java.sql.Time.class, new SqlTimeTypeHandler());register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());register(String.class, JdbcType.SQLXML, new SqlxmlTypeHandler());register(Instant.class, new InstantTypeHandler());register(LocalDateTime.class, new LocalDateTimeTypeHandler());register(LocalDate.class, new LocalDateTypeHandler());register(LocalTime.class, new LocalTimeTypeHandler());register(OffsetDateTime.class, new OffsetDateTimeTypeHandler());register(OffsetTime.class, new OffsetTimeTypeHandler());register(ZonedDateTime.class, new ZonedDateTimeTypeHandler());register(Month.class, new MonthTypeHandler());register(Year.class, new YearTypeHandler());register(YearMonth.class, new YearMonthTypeHandler());register(JapaneseDate.class, new JapaneseDateTypeHandler());// issue #273register(Character.class, new CharacterTypeHandler());register(char.class, new CharacterTypeHandler());
}
以register(Boolean.class, new BooleanTypeHandler())为例
public <T> void register(Class<T> javaType, TypeHandler<? extends T> typeHandler) {register((Type) javaType, typeHandler);
}private <T> void register(Type javaType, TypeHandler<? extends T> typeHandler) {MappedJdbcTypes mappedJdbcTypes = typeHandler.getClass().getAnnotation(MappedJdbcTypes.class);if (mappedJdbcTypes != null) {for (JdbcType handledJdbcType : mappedJdbcTypes.value()) {register(javaType, handledJdbcType, typeHandler);}if (mappedJdbcTypes.includeNullJdbcType()) {register(javaType, null, typeHandler);}} else {register(javaType, null, typeHandler);}
}private void register(Type javaType, JdbcType jdbcType, TypeHandler<?> handler) {if (javaType != null) {Map<JdbcType, TypeHandler<?>> map = typeHandlerMap.get(javaType);if (map == null || map == NULL_TYPE_HANDLER_MAP) {map = new HashMap<>();}map.put(jdbcType, handler);// 注册到 typeHandlerMap 中typeHandlerMap.put(javaType, map);}// 注册到 allTypeHandlersMap 中allTypeHandlersMap.put(handler.getClass(), handler);
}
以register(JdbcType.BOOLEAN, new BooleanTypeHandler());为例
public void register(JdbcType jdbcType, TypeHandler<?> handler) {jdbcTypeHandlerMap.put(jdbcType, handler);
}

UnknowTypeHandler

public class UnknownTypeHandler extends BaseTypeHandler<Object> {// ObjectTypeHandler默认的实现为 // - ps.setObject(i, parameter)// - rs.getObject(columnName)private static final ObjectTypeHandler OBJECT_TYPE_HANDLER = new ObjectTypeHandler();private final Configuration config;private final Supplier<TypeHandlerRegistry> typeHandlerRegistrySupplier;public UnknownTypeHandler(Configuration configuration) {this.config = configuration;// UnknowTypeHandler依赖于 configuration的 TypeHandlerRegistry 实现this.typeHandlerRegistrySupplier = configuration::getTypeHandlerRegistry;}@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)throws SQLException {// 先去解析(查找)对应的 TypeHandlerTypeHandler handler = resolveTypeHandler(parameter, jdbcType);// 使用解析(查找) 的 TypeHandler 完成事情handler.setParameter(ps, i, parameter, jdbcType);}@Overridepublic Object getNullableResult(ResultSet rs, String columnName)throws SQLException {TypeHandler<?> handler = resolveTypeHandler(rs, columnName);return handler.getResult(rs, columnName);}@Overridepublic Object getNullableResult(ResultSet rs, int columnIndex)throws SQLException {TypeHandler<?> handler = resolveTypeHandler(rs.getMetaData(), columnIndex);if (handler == null || handler instanceof UnknownTypeHandler) {handler = OBJECT_TYPE_HANDLER;}return handler.getResult(rs, columnIndex);}@Overridepublic Object getNullableResult(CallableStatement cs, int columnIndex)throws SQLException {return cs.getObject(columnIndex);}private TypeHandler<?> resolveTypeHandler(Object parameter, JdbcType jdbcType) {// 将返回的 handlerTypeHandler<?> handler;if (parameter == null) {// 如果参数为null,则返回 默认的 ObjectTypeHandlerhandler = OBJECT_TYPE_HANDLER;} else {// 如果参数不为null,则根据参数的javaType和对应的jdbcType来使用configuration中的typeHandlerRegistry来获取对应的typeHandler了handler = typeHandlerRegistrySupplier.get().getTypeHandler(parameter.getClass(), jdbcType);// 如果找不到,则返回默认的 ObjectTypeHandlerif (handler == null || handler instanceof UnknownTypeHandler) {handler = OBJECT_TYPE_HANDLER;}}return handler;}private TypeHandler<?> resolveTypeHandler(ResultSet rs, String column) {try {Map<String,Integer> columnIndexLookup;columnIndexLookup = new HashMap<>();ResultSetMetaData rsmd = rs.getMetaData();int count = rsmd.getColumnCount();boolean useColumnLabel = config.isUseColumnLabel();for (int i = 1; i <= count; i++) {String name = useColumnLabel ? rsmd.getColumnLabel(i) : rsmd.getColumnName(i);columnIndexLookup.put(name,i);}Integer columnIndex = columnIndexLookup.get(column);TypeHandler<?> handler = null;if (columnIndex != null) {handler = resolveTypeHandler(rsmd, columnIndex);}if (handler == null || handler instanceof UnknownTypeHandler) {handler = OBJECT_TYPE_HANDLER;}return handler;} catch (SQLException e) {throw new TypeException("Error determining JDBC type for column " + column + ".  Cause: " + e, e);}}private TypeHandler<?> resolveTypeHandler(ResultSetMetaData rsmd, Integer columnIndex) {TypeHandler<?> handler = null;JdbcType jdbcType = safeGetJdbcTypeForColumn(rsmd, columnIndex);Class<?> javaType = safeGetClassForColumn(rsmd, columnIndex);if (javaType != null && jdbcType != null) {handler = typeHandlerRegistrySupplier.get().getTypeHandler(javaType, jdbcType);} else if (javaType != null) {handler = typeHandlerRegistrySupplier.get().getTypeHandler(javaType);} else if (jdbcType != null) {handler = typeHandlerRegistrySupplier.get().getTypeHandler(jdbcType);}return handler;}private JdbcType safeGetJdbcTypeForColumn(ResultSetMetaData rsmd, Integer columnIndex) {try {return JdbcType.forCode(rsmd.getColumnType(columnIndex));} catch (Exception e) {return null;}}private Class<?> safeGetClassForColumn(ResultSetMetaData rsmd, Integer columnIndex) {try {return Resources.classForName(rsmd.getColumnClassName(columnIndex));} catch (Exception e) {return null;}}
}
http://www.dtcms.com/a/561849.html

相关文章:

  • Vue项目中的Electron桌面应用开发实践指南
  • 如何运行asp.net网站wordpress怎么导入demo文件
  • focusPolicy/setFocusPolicy(FocusPolicy),styleSheet
  • 六.DockerFile解析及其应用部署
  • wp企业网站模板数据分析师事务所
  • AWS DMS 大规模数据库迁移:完全加载+持续复制最佳实践
  • 阿里巴巴六边形架构-从解耦到可测试的架构设计利器
  • 中国世界排名前500大学seo网上培训多少钱
  • 做网站做哪个行业好商城网站建设高端
  • 正规网站建设建设公司雅安建设局网站
  • 如何在Java中整合Redis?
  • 官方网站是什么意思免费链接生成器
  • 增加网站访客珠宝首饰商城网站建设
  • 网络通信的奥秘:TCP与UDP详解(三)
  • 理财网站开发最近中国新闻
  • 详解网络安全免杀对抗:攻防的猫鼠游戏
  • 【开题答辩全过程】以 高考志愿分析系统为例,包含答辩的问题和答案
  • ESP-IDF基础入门(2)
  • 中国建设官方网站首页网上商城推广方案
  • 网站建设必须安装程序天眼查公司信息查询
  • 织梦网站首页是哪个文件网站手机访问跳转代码
  • 博弈dp|凸包|math分类
  • 网站浏览器兼容性问题wordpress手机端网站
  • 中国建设银行预约网站xampp做网站
  • VS2019+CUDA 编译通过但有错误提示
  • 有哪些做问卷调查挣钱的网站单页 网站模板
  • 承德网站制作数据库营销案例
  • 32位汇编:实验9分支程序结构使用
  • Kanass实践指南(3) - 开发团队如何通过kanass有效管控开发任务
  • 基于双向时序卷积网络与双向门控循环单元(BiTCN-BiGRU)混合模型的时间序列预测(Matlab源码)