问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

MyBatis类型转换错误的终极解决方案

创作时间:
作者:
@小白创作中心

MyBatis类型转换错误的终极解决方案

引用
CSDN
12
来源
1.
https://m.blog.csdn.net/m0_73310000/article/details/138138943
2.
https://blog.csdn.net/weixin_43968234/article/details/103565911
3.
https://m.blog.csdn.net/weixin_30485379/article/details/99395786
4.
https://m.blog.csdn.net/qq_47155894/article/details/124711290
5.
https://m.blog.csdn.net/lzq2357639195/article/details/136347956
6.
https://blog.csdn.net/jokeMqc/article/details/81326109
7.
https://blog.csdn.net/weixin_42988781/article/details/107144439
8.
https://www.cnblogs.com/listenerxx/articles/14190710.html
9.
https://www.cnblogs.com/dw3306/p/16821591.html
10.
https://www.cnblogs.com/xyyou/articles/10848310.html
11.
https://mybatis.org/mybatis-3/configuration.html
12.
https://www.finclip.com/news/f/31306.html

在Java后端开发中,MyBatis作为一款优秀的持久层框架,被广泛应用于各种企业级应用中。然而,在使用MyBatis的过程中,开发者经常会遇到各种类型转换错误,这些错误不仅让人头疼,还可能严重影响项目的开发进度。本文将深入探讨MyBatis中常见的类型转换错误及其解决方案,帮助开发者更好地应对这些问题。

常见的类型转换错误场景

动态SQL中的字符串比较错误

在使用MyBatis的动态SQL时,一个常见的错误是字符串比较时的格式问题。例如,当使用标签进行条件判断时,如果字符串比较的格式不正确,可能会导致NumberFormatException。

<where>
  <if test="name != null and name != ' '">
    name like concat('%',#{name},'%')
  </if>
</where>

上述代码中,name != ' '的条件判断会导致问题,因为单引号内的空格会被解析为一个空格字符,而不是一个空字符串。正确的写法应该是:

<where>
  <if test="name != null and name != ''">
    name like concat('%',#{name},'%')
  </if>
</where>

参数类型不匹配错误

另一个常见的类型转换错误是参数类型与数据库字段类型不匹配。例如,当数据库字段是int类型,而传入的参数却是Long类型时,就会引发argument type mismatch错误。

java.lang.RuntimeException: org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.executor.ExecutorException: Error selecting key or setting result to parameter object. Cause: org.apache.ibatis.reflection.ReflectionException: Could not set property ‘id’ of ‘class xxxxxxxx’ with value ‘37997’ Cause: java.lang.IllegalArgumentException: argument type mismatch

解决这类问题的关键是确保参数类型与数据库字段类型完全一致。例如,如果数据库字段是int类型,那么在实体类中对应的属性也应该是Integer类型。

字符类型转换错误

在处理字符类型字段时,类型转换错误也时有发生。例如,当尝试将一个字符类型的字段与数值进行比较时,会引发NumberFormatException。

java.lang.NumberFormatException: For input string: "高"

这种错误通常发生在SQL语句中对字符类型字段的不当处理。例如:

<when test='param.HD_ZB_LEVEL != null and param.HD_ZB_LEVEL == "高"'>
  AND HD_ZB_ZQYJ004 = '经营状况预警'
</when>

正确的做法是确保所有字符串常量都使用双引号包裹,并避免在比较操作中进行隐式的类型转换。

深入理解TypeHandler机制

为了从根本上解决类型转换问题,我们需要深入了解MyBatis的TypeHandler机制。TypeHandler是MyBatis中用于处理Java类型和JDBC类型之间转换的核心组件。

TypeHandler的工作原理

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;
}
  • setParameter方法用于将Java类型的数据转换为JDBC类型
  • getResult方法用于将查询结果转换为Java类型

自定义TypeHandler

在实际开发中,我们经常需要自定义TypeHandler来处理特定的类型转换需求。例如,当数据库字段存储的是int类型(如1表示男,2表示女),而前端传递的是字符串类型("男"或"女")时,就需要一个自定义的TypeHandler来进行转换。

自定义TypeHandler可以通过实现TypeHandler接口或继承BaseTypeHandler抽象类来完成。以下是一个基于BaseTypeHandler的性别转换处理器示例:

@MappedJdbcTypes(JdbcType.INTEGER)
@MappedTypes(String.class)
public class GenderTypeHandler extends BaseTypeHandler<String> {
  @Override
  public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
    ps.setInt(i, "男".equals(parameter) ? 1 : 2);
  }

  @Override
  public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
    return rs.getInt(columnName) == 1 ? "男" : "女";
  }

  @Override
  public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    return rs.getInt(columnIndex) == 1 ? "男" : "女";
  }

  @Override
  public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    return cs.getInt(columnIndex) == 1 ? "男" : "女";
  }
}

TypeHandler的配置

自定义的TypeHandler需要在MyBatis中进行配置才能生效。有两种常见的配置方式:

  1. 在application.properties中配置:
mybatis.type-handlers-package=cn.cb.demo.typehandler
  1. 通过Java配置类配置:
@Bean("sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
  SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
  sqlSessionFactoryBean.setDataSource(dataSource);
  sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATOIN));
  org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
  configuration.getTypeHandlerRegistry().register(GenderTypeHandler.class);
  sqlSessionFactoryBean.setConfiguration(configuration);
  return sqlSessionFactoryBean.getObject();
}

最佳实践和建议

为了避免类型转换错误,开发者在使用MyBatis时可以遵循以下最佳实践:

  1. 严格检查参数类型:确保前端传递的参数类型与后端定义的类型完全一致。
  2. 使用TypeHandler处理复杂类型转换:对于需要特殊处理的类型转换,建议使用自定义TypeHandler。
  3. 代码审查和单元测试:通过代码审查和单元测试及时发现潜在的类型转换问题。
  4. 日志记录:在关键位置添加日志记录,帮助定位和调试类型转换错误。

掌握MyBatis的类型转换机制不仅能帮助我们解决眼前的问题,更能提升整体开发效率和代码质量。通过理解和运用TypeHandler,我们可以更灵活地处理各种数据类型转换需求,让MyBatis真正成为我们开发中的得力助手。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号