001/* 002 * Copyright (c) 2022-2025, Mybatis-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.mybatisflex.core.mybatis; 017 018import com.mybatisflex.core.FlexConsts; 019import com.mybatisflex.core.exception.FlexExceptions; 020import com.mybatisflex.core.util.EnumWrapper; 021import org.apache.ibatis.mapping.BoundSql; 022import org.apache.ibatis.mapping.MappedStatement; 023import org.apache.ibatis.scripting.defaults.DefaultParameterHandler; 024import org.apache.ibatis.type.TypeHandler; 025import org.apache.ibatis.type.TypeHandlerRegistry; 026 027import java.sql.PreparedStatement; 028import java.sql.SQLException; 029import java.util.Map; 030 031/** 032 * 向 {@link PreparedStatement} 中的占位符设置值。 033 * 034 * @author michael 035 * @author 王帅 036 */ 037public class SqlArgsParameterHandler extends DefaultParameterHandler { 038 039 private final TypeHandlerRegistry typeHandlerRegistry; 040 041 public SqlArgsParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) { 042 super(mappedStatement, parameterObject, boundSql); 043 this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry(); 044 } 045 046 @Override 047 public void setParameters(PreparedStatement ps) { 048 try { 049 doSetParameters(ps); 050 } catch (SQLException e) { 051 throw FlexExceptions.wrap(e); 052 } 053 } 054 055 @SuppressWarnings({"rawtypes", "unchecked"}) 056 private void doSetParameters(PreparedStatement ps) throws SQLException { 057 Object[] sqlArgs; 058 Map parameters = (Map) getParameterObject(); 059 if (parameters.containsKey(FlexConsts.RAW_ARGS) 060 || (sqlArgs = (Object[]) parameters.get(FlexConsts.SQL_ARGS)) == null 061 || sqlArgs.length == 0) { 062 super.setParameters(ps); 063 return; 064 } 065 066 int index = 1; 067 for (Object value : sqlArgs) { 068 // 设置 NULL 值 069 if (value == null) { 070 // ps.setNull(index++, Types.NULL); 071 // 此处不应该使用 setNull(index++, Types.NULL),通过 setObject 传入 null 值,有 jdbc 驱动自行验证类型即可 072 // 使用 setNull 在 db2 等数据库下,Types.NULL 并非其需要类型 073 ps.setObject(index++, null); 074 continue; 075 } 076 077 // 通过配置的 TypeHandler 去设置值 078 if (value instanceof TypeHandlerObject) { 079 ((TypeHandlerObject) value).setParameter(ps, index++); 080 continue; 081 } 082 083 TypeHandler typeHandler = typeHandlerRegistry.getTypeHandler(value.getClass()); 084 if (typeHandler == null) { 085 typeHandler = typeHandlerRegistry.getUnknownTypeHandler(); 086 } 087 088 // 此处的 jdbcType 可以为 null 的,原因是 value 不为 null, 089 // 只有 value 为 null 时, jdbcType 不允许为 null 090 typeHandler.setParameter(ps, index++, value, null); 091 } 092 } 093 094}