package jef.database.wrapper.variable; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Arrays; import java.util.Date; import java.util.List; import jef.common.log.LogUtil; import jef.database.IQueryableEntity; import jef.database.dialect.DatabaseDialect; import jef.database.dialect.type.ColumnMapping; import jef.database.query.ConditionQuery; import jef.database.support.SqlLog; import jef.tools.IOUtils; public final class BindVariableContext { private PreparedStatement psmt; private DatabaseDialect db; private final SqlLog logMessage; public BindVariableContext(PreparedStatement psmt, DatabaseDialect profile, SqlLog sb) { this.psmt = psmt; this.logMessage = sb; this.db = profile; } public SqlLog getLogMessage() { return logMessage; } private void log(int count, Object fieldName, Object value) { logMessage.append(count, fieldName, value); } private Object setValueInPsmt(int count, Object value) throws SQLException { if (value != null) { if ((value instanceof File)) { File file = (File) value; try { psmt.setBinaryStream(count, IOUtils.getInputStream(file), file.length()); } catch (IOException e) { throw new IllegalArgumentException(); } return value; } else if (value instanceof byte[]) { byte[] buf = (byte[]) value; psmt.setBinaryStream(count, new ByteArrayInputStream(buf), buf.length); return value; } else if (value instanceof Enum<?>) { value = ((Enum<?>) value).name(); } else if (value instanceof Character) { value = value.toString(); } } psmt.setObject(count, value); return value; } /** * 对于绑定变量的SQL对象进行参数赋值 * * @param psmt * @param count * @param value * @param cType * @throws SQLException */ protected Object setValueInPsmt(int count, Object value, ColumnMapping cType) throws SQLException { if (cType == null) { if (value.getClass() == java.util.Date.class) { value = db.toTimestampSqlParam((Date) value); } psmt.setObject(count, value); } else { value = cType.jdbcSet(psmt, value, count, db); } return value; } /** * */ public enum SqlType { INSERT, UPDATE, DELETE, SELECT } /** * 设置绑定变量值 场景1 * * 用途2 添加Batch任务,可以是Insert或者Update 注意1: * Update任务只会更新Batch创建时指定的字段,不会更新后来新增的字段 * * @param da * 查询对象 * @param writeFields * 需要写入的字段,Insert或者update * @param whereFiels * 条件字段 * @return 如果有where部分,返回where实际使用的参数 * @throws SQLException */ public List<Object> setVariables(ConditionQuery da, List<Variable> writeFields, List<Variable> whereFiels) throws SQLException { int count = 0; // 更新值绑定 if (writeFields != null) { for (Variable field : writeFields) { Object value = field.jdbcSet(this, ++count, da); this.log(count, field.name(), value); } } // 条件绑定 if (whereFiels != null) { Object[] actualWhereParams = new Object[whereFiels.size()]; int n = 0; for (Variable field : whereFiels) { Object value = field.jdbcSet(this, ++count, da); this.log(count, field.name(), value); actualWhereParams[n++] = value; } return Arrays.asList(actualWhereParams); } return null; } /** * 这个方法是在executeSQL和selectBySQL等直接SQL层面的情况下按参数顺序绑定变量使用的 * * @param st * @param params * @param debug * @throws SQLException */ public void setVariables(List<?> params) throws SQLException { int n = 0; for (Object value : params) { n++; try { value = this.setValueInPsmt(n, value); this.log(n, "", value); } catch (SQLException e) { String type = value == null ? "null" : value.getClass().getName(); String message = "Setting bind variable [" + n + "] error, type=" + type; LogUtil.error(message); throw e; } } } /** * 为Insert语句设置绑定变量 * * @param obj * 要插入的对内 * @param fields * @throws SQLException */ public void setInsertVariables(IQueryableEntity obj, List<ColumnMapping> fields) throws SQLException { int count = 0; for (ColumnMapping field : fields) { count++; Object value = field.getFieldAccessor().get(obj); try { value = this.setValueInPsmt(count, value, field); this.log(count, field, value); } catch (ClassCastException e) { throw new SQLException("The query param type error, field=" + field.fieldName() + ":" + e.getMessage()); } } } }