当前位置:Gxlcms > 数据库问题 > SqlSession对象之ParameterHandler

SqlSession对象之ParameterHandler

时间:2021-07-01 10:21:17 帮助过:5人阅读

上一篇讲了StatementHandler,其中有ParameterHandler(参数处理器)是在StatementHandler被创建时被创建的。下面对ParameterHandler进行说明。其代码如下:

  1. <code>public interface ParameterHandler {
  2. Object getParameterObject();
  3. void setParameters(PreparedStatement ps) throws SQLException;
  4. }</code>

它只有两个方法,其中getParameterObject()是获取参数的,而setParameters()是设置参数的。

ParameterHandler只有一个实现类DefaultParameterHandler,在查看DefaultParameterHandler代码之前首先了解DefaultParameterHandler中的相关属性。代码如下所示:

  1. <code>//类型转换处理器:映射Java中数据类型与数据库中数据类型对应关系
  2. private final TypeHandlerRegistry typeHandlerRegistry;
  3. //映射sql语句与数据库操作对象关系以及sql关联的sql标签信息
  4. private final MappedStatement mappedStatement;
  5. //存储的需要进行赋值参数内容
  6. private final Object parameterObject;
  7. //输送的具体的sql语句
  8. private final BoundSql boundSql;
  9. //包含myBatis框架核心配置文件信息和sql映射文件信息
  10. private final Configuration configuration;</code>

下面查看DefaultParameterHandler中setParameters()的实现,代码如下所示:

  1. <code> public void setParameters(PreparedStatement ps) {
  2. ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
  3. //// parameterMappings是对#{}里给出的参数信息的封装,即这个SQL是个参数化SQL时会存在(SQL语句中带占位符?)
  4. List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
  5. if (parameterMappings != null) {
  6. for (int i = 0; i < parameterMappings.size(); i++) {
  7. ParameterMapping parameterMapping = parameterMappings.get(i);
  8. //存储过程才存在输出参数,所以当参数不是输出参数的时候,就需要设置
  9. if (parameterMapping.getMode() != ParameterMode.OUT) {
  10. Object value;
  11. //这里的propertyName对应的是一个additionalParameters Map对象经过封装的key值,而不是Bean的属性
  12. String propertyName = parameterMapping.getProperty();
  13. //判断propertyName是additionalParameters中的key
  14. if (boundSql.hasAdditionalParameter(propertyName)) {
  15. value = boundSql.getAdditionalParameter(propertyName);
  16. } else if (parameterObject == null) {
  17. value = null;
  18. }
  19. //如果在typeHandlerRegistry中已经注册了这个参数的Class对象,value直接等于Method传进来的参数
  20. else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
  21. value = parameterObject;
  22. }
  23. //否则是Map或Bean,List或Array被封装成了Map,通过Key得到Value;Bean是通过封装的MataObject对象,Bean通过反射得到,再用propertyName得到相应的Value。
  24. else {
  25. MetaObject metaObject = configuration.newMetaObject(parameterObject);
  26. value = metaObject.getValue(propertyName);
  27. }
  28. //得到parameterMapping的TypeHandler,均为IntegerTypeHandler
  29. TypeHandler typeHandler = parameterMapping.getTypeHandler();
  30. //得到相应parameterMapping的JdbcType,如果没有在#{}中显式的指定JdbcType,则为null
  31. JdbcType jdbcType = parameterMapping.getJdbcType();
  32. //当value和jdbcType都为null执行执行setNull操作时,会报OTHER的错误,因此指定JdbcType
  33. if (value == null && jdbcType == null) {
  34. jdbcType = configuration.getJdbcTypeForNull();
  35. }
  36. try {
  37. //具体实现ps.set***
  38. typeHandler.setParameter(ps, i + 1, value, jdbcType);
  39. } catch (TypeException e) {
  40. throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
  41. } catch (SQLException e) {
  42. throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
  43. }
  44. }
  45. }
  46. }
  47. }</code>

上面的的setParameter()是在BaseTypeHandler中实现的,它是IntegerTypeHandler等的父类,这里采用了模板模式。setParameter()的代码如下:

  1. <code> public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
  2. if (parameter == null) {
  3. if (jdbcType == null) {
  4. throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
  5. }
  6. try {
  7. //执行PreparedStatement的setNull方法
  8. ps.setNull(i, jdbcType.TYPE_CODE);
  9. } catch (SQLException e) {
  10. throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . " +
  11. "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. " +
  12. "Cause: " + e, e);
  13. }
  14. } else {
  15. try {
  16. //进行参数设置,是抽象方法,具体的实现在子类中
  17. setNonNullParameter(ps, i, parameter, jdbcType);
  18. } catch (Exception e) {
  19. throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . " +
  20. "Try setting a different JdbcType for this parameter or a different configuration property. " +
  21. "Cause: " + e, e);
  22. }
  23. }
  24. }</code>

下面对上面所说的setNull()进行说名:

  1. <code>public void setNull(int parameterIndex, int sqlType) throws SQLException{}
  2. //parameterIndex:整形参数,第一个为1,第二个为2...
  3. //sqlType必须为java.sql.Types 中定义的SQL类型代码
  4. //若parameterIndex 不对应于 SQL 语句中的参数标记;发生数据库访问错误;或在关闭的 PreparedStatement上调用此方法,会抛出SQLException异常。</code>

由上面代码知,当SQL类型代码为1111(OTHER)时,就会出现报错:java.sql.SQLException: 无效的列类型: 1111,解决方案是在其后加上jdbcType,示例代码如下:

  1. <code><insert id="insertUser" parameterType="com.luis.domain.User">
  2. insert into t_user(s_id,name,age)
  3. values (
  4. #{SId,jdbcType=INTEGER},
  5. #{name,jdbcType=VARCHAR},
  6. #{age,jdbcType=INTEGER}
  7. );
  8. </insert></code>

另有博主验证在ibatis2 可以正常的执行 数据库可以正常的插入数据。

参见:http://www.cnblogs.com/panxuejun/p/6163779.html

SqlSession对象之ParameterHandler

标签:等于   一个   into   new   size   amp   with   获取   信息   

人气教程排行