001/** 002 * Copyright (c) 2022-2023, 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 org.apache.ibatis.mapping.BoundSql; 020import org.apache.ibatis.mapping.MappedStatement; 021import org.apache.ibatis.scripting.defaults.DefaultParameterHandler; 022 023import java.sql.PreparedStatement; 024import java.sql.SQLException; 025import java.util.Date; 026import java.util.Map; 027 028public class SqlArgsParameterHandler extends DefaultParameterHandler { 029 030 private final Map parameterObject; 031 032 033 public SqlArgsParameterHandler(MappedStatement mappedStatement, Map parameterObject, BoundSql boundSql) { 034 super(mappedStatement, parameterObject, boundSql); 035 this.parameterObject = parameterObject; 036 } 037 038 039 @Override 040 public void setParameters(PreparedStatement ps) { 041 try { 042 doSetParameters(ps); 043 } catch (SQLException e) { 044 throw new RuntimeException(e); 045 } 046 } 047 048 049 private void doSetParameters(PreparedStatement ps) throws SQLException { 050 Object[] sqlArgs = (Object[]) ((Map<?, ?>) parameterObject).get(FlexConsts.SQL_ARGS); 051 if (sqlArgs != null && sqlArgs.length > 0) { 052 int index = 1; 053 for (Object value : sqlArgs) { 054 //通过配置的 TypeHandler 去设置内容 055 if (value instanceof TypeHandlerObject) { 056 ((TypeHandlerObject) value).setParameter(ps, index++); 057 } 058 //在 Oracle、SqlServer 中 TIMESTAMP、DATE 类型的数据是支持 java.util.Date 给值的 059 else if (value instanceof java.util.Date) { 060 setDateParameter(ps, (Date) value, index++); 061 } else if (value instanceof byte[]) { 062 ps.setBytes(index++, (byte[]) value); 063 } else { 064 /** 在 MySql,Oracle 等驱动中,通过 PreparedStatement.setObject 后,驱动会自动根据 value 内容进行转换 065 * 源码可参考: {{@link com.mysql.jdbc.PreparedStatement#setObject(int, Object)} 066 **/ 067 ps.setObject(index++, value); 068 } 069 } 070 } else { 071 super.setParameters(ps); 072 } 073 } 074 075 /** 076 * Oracle、SqlServer 需要主动设置下 date 类型 077 * MySql 通过 setObject 后会自动转换,具体查看 MySql 驱动源码 078 * 079 * @param ps PreparedStatement 080 * @param value date value 081 * @param index set to index 082 * @throws SQLException 083 */ 084 private void setDateParameter(PreparedStatement ps, Date value, int index) throws SQLException { 085 if (value instanceof java.sql.Date) { 086 ps.setDate(index, (java.sql.Date) value); 087 } else if (value instanceof java.sql.Timestamp) { 088 ps.setTimestamp(index, (java.sql.Timestamp) value); 089 } else { 090 ps.setTimestamp(index, new java.sql.Timestamp(value.getTime())); 091 } 092 } 093}