All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.tenmg.sqltool.sql.dialect.AbstractSQLDialect Maven / Gradle / Ivy

package cn.tenmg.sqltool.sql.dialect;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import cn.tenmg.dsl.utils.StringUtils;
import cn.tenmg.dsql.utils.PlaceHolderUtils;
import cn.tenmg.sql.paging.SQL;
import cn.tenmg.sql.paging.SQLMetaData;
import cn.tenmg.sql.paging.SQLPagingDialect;
import cn.tenmg.sql.paging.dialect.AbstractSQLPagingDialect;
import cn.tenmg.sql.paging.utils.SQLUtils;
import cn.tenmg.sqltool.config.annotion.Column;
import cn.tenmg.sqltool.config.annotion.Id;
import cn.tenmg.sqltool.exception.ColumnNotFoundException;
import cn.tenmg.sqltool.exception.DataAccessException;
import cn.tenmg.sqltool.exception.NoColumnForUpdateException;
import cn.tenmg.sqltool.exception.PkNotFoundException;
import cn.tenmg.sqltool.sql.MergeSQL;
import cn.tenmg.sqltool.sql.SQLDialect;
import cn.tenmg.sqltool.sql.UpdateSQL;
import cn.tenmg.sqltool.sql.meta.EntityMeta;
import cn.tenmg.sqltool.sql.meta.FieldMeta;
import cn.tenmg.sqltool.sql.utils.EntityUtils;
import cn.tenmg.sqltool.utils.JDBCExecuteUtils;

/**
 * 抽象SQL方言。封装方言基本方法
 * 
 * @author 赵伟均 [email protected]
 *
 * @since 1.1.0
 */
public abstract class AbstractSQLDialect extends AbstractSQLPagingDialect implements SQLDialect {

	private static final String UPDATE = "UPDATE ${tableName} SET ${sets} WHERE ${condition}";

	protected static final String TABLE_NAME = "tableName", COLUMNS = "columns", VALUES = "values", SETS = "sets",
			LEFT_COLUMN_NAME = "columnName", RIGHT_COLUMN_NAME = "columnName";

	protected static final int SELECT_LEN = "SELECT".length();

	/**
	 * 获取SQL分页查询方言
	 * 
	 * @return SQL分页查询方言
	 */
	abstract SQLPagingDialect getSQLPagingDialect();

	/**
	 * 获取更新语句的SET子句模板。例如Mysql数据库为${columnName}=?
	 */
	abstract String getUpdateSetTemplate();

	/**
	 * 获取更新语句非空时SET子句模板。例如Mysql数据库为${columnName}=IFNULL(${columnName}, ?)
	 * 
	 * @return 返回非空时SET子句模板
	 */
	abstract String getUpdateSetIfNotNullTemplate();

	/**
	 * 获取额外的SQL模板参数名集,用于初始化SQL模板参数。已初始化的模板参数有columns、values、sets。columns用于表示插入的列,values表示插入的参数,sets表示记录已存在时的更新表达式。这些参数将在后续运行过程中逐步追加字符生成
	 */
	abstract List getExtSQLTemplateParamNames();

	/**
	 * 获取保存数据SQL模板。
	 * 
	 * @return 返回保存数据SQL模板
	 */
	abstract String getSaveSQLTemplate();

	/**
	 * 获取不存在则插入数据SQL模板。
	 * 
	 * @return 返回不存在则插入数据SQL模板
	 */
	abstract String getInsertIfNotExistsSQLTemplate();

	/**
	 * 获取需要添加逗号的参数名列表。处理第2列之前,将需要添加逗号的模板参数均添加逗号
	 * 
	 * @return 返回需要添加逗号的参数名列表
	 */
	abstract List getNeedsCommaParamNames();

	/**
	 * 保存时每个列的处理方法。根据需要向个各模板参数追加字符串
	 * 
	 * @param columnName
	 *            列名
	 * @param templateParams
	 *            SQL模板参数集
	 */
	abstract void handleColumnWhenSave(String columnName, Map templateParams);

	/**
	 * 保存时每个主键列的处理方法。根据需要向个特定模板参数追加字符串
	 * 
	 * @param columnName
	 *            主键列名
	 * @param templateParams
	 *            SQL模板参数集
	 * @param notFirst
	 *            是否非第一个主键列
	 */
	abstract void handleIdColumnWhenSave(String columnName, Map templateParams,
			boolean notFirst);

	/**
	 * 获取SET子句模板。例如Mysql数据库为${columnName}=VALUES(${columnName})
	 * 
	 * @return 返回SET子句模板
	 */
	abstract String getSetTemplate();

	/**
	 * 获取非空时SET子句模板。例如Mysql数据库为${columnName}=IFNULL(VALUES(${columnName}), ${columnName})
	 * 
	 * @return 返回非空时SET子句模板
	 */
	abstract String getSetIfNotNullTemplate();

	@Override
	public  UpdateSQL update(Class type) {
		EntityMeta entityMeta = EntityUtils.getCachedEntityMeta(type);
		boolean hasId = false, hasGeneralColumn = false;
		StringBuilder sets = new StringBuilder(), condition = new StringBuilder();
		List generalFields = new ArrayList(), idFields = new ArrayList();
		try {
			if (entityMeta == null) {
				Class current = type;
				Set fieldSet = new HashSet();
				List fieldMetas = new ArrayList();
				while (!Object.class.equals(current)) {
					Field[] declaredFields = current.getDeclaredFields();
					for (int i = 0; i < declaredFields.length; i++) {
						Field field = declaredFields[i];
						String fieldName = field.getName();
						if (!fieldSet.contains(fieldName)) {
							fieldSet.add(fieldName);
							Column column = field.getAnnotation(Column.class);
							if (column != null) {
								field.setAccessible(true);
								String columnName = column.name();
								if (StringUtils.isBlank(columnName)) {
									columnName = StringUtils.camelToUnderline(fieldName, true);
								}
								FieldMeta fieldMeta = new FieldMeta(field, columnName);
								if (field.getAnnotation(Id.class) == null) {// 组织已存在时的更新子句
									fieldMeta.setId(false);
									generalFields.add(field);
									if (hasGeneralColumn) {
										sets.append(JDBCExecuteUtils.COMMA_SPACE);
									} else {
										hasGeneralColumn = true;
									}
									sets.append(PlaceHolderUtils.replace(getUpdateSetIfNotNullTemplate(), "columnName",
											columnName));
								} else {
									fieldMeta.setId(true);
									idFields.add(field);
									if (hasId) {
										condition.append(JDBCExecuteUtils.SPACE_AND_SPACE);
									} else {
										hasId = true;
									}
									condition.append(columnName).append(JDBCExecuteUtils.SPACE_EQ_SPACE)
											.append(SQLUtils.PARAM_MARK);
								}
								fieldMetas.add(fieldMeta);
							}
						}
					}
					current = current.getSuperclass();
				}
				entityMeta = new EntityMeta(EntityUtils.getTableName(type), fieldMetas);
				EntityUtils.cacheEntityMeta(type, entityMeta);
			} else {
				List fieldMetas = entityMeta.getFieldMetas();
				for (int i = 0, size = fieldMetas.size(); i < size; i++) {
					FieldMeta fieldMeta = fieldMetas.get(i);
					Field field = fieldMeta.getField();
					String columnName = fieldMeta.getColumnName();
					if (fieldMeta.isId()) {
						idFields.add(field);
						if (hasId) {
							condition.append(JDBCExecuteUtils.SPACE_AND_SPACE);
						} else {
							hasId = true;
						}
						condition.append(columnName).append(JDBCExecuteUtils.SPACE_EQ_SPACE).append(SQLUtils.PARAM_MARK);
					} else {// 组织已存在时的更新子句
						generalFields.add(field);
						if (hasGeneralColumn) {
							sets.append(JDBCExecuteUtils.COMMA_SPACE);
						} else {
							hasGeneralColumn = true;
						}
						sets.append(
								PlaceHolderUtils.replace(getUpdateSetIfNotNullTemplate(), "columnName", columnName));
					}
				}
			}
		} catch (IllegalArgumentException e) {
			throw new DataAccessException(e);
		}
		return updateSQL(type, hasId, hasGeneralColumn, entityMeta.getTableName(), sets, condition, generalFields,
				idFields);
	}

	@Override
	public  UpdateSQL update(Class type, String... hardFields) {
		Set hardFieldSet = new HashSet();
		for (int i = 0; i < hardFields.length; i++) {
			hardFieldSet.add(hardFields[i]);
		}
		EntityMeta entityMeta = EntityUtils.getCachedEntityMeta(type);
		boolean hasId = false, hasGeneralColumn = false;
		StringBuilder sets = new StringBuilder(), condition = new StringBuilder();
		List generalFields = new ArrayList(), idFields = new ArrayList();
		String updateSetTemplate;
		try {
			if (entityMeta == null) {
				Class current = type;
				Set fieldSet = new HashSet();
				List fieldMetas = new ArrayList();
				while (!Object.class.equals(current)) {
					Field[] declaredFields = current.getDeclaredFields();
					for (int i = 0; i < declaredFields.length; i++) {
						Field field = declaredFields[i];
						String fieldName = field.getName();
						if (!fieldSet.contains(fieldName)) {
							fieldSet.add(fieldName);
							Column column = field.getAnnotation(Column.class);
							if (column != null) {
								field.setAccessible(true);
								String columnName = column.name();
								if (StringUtils.isBlank(columnName)) {
									columnName = StringUtils.camelToUnderline(fieldName, true);
								}
								FieldMeta fieldMeta = new FieldMeta(field, columnName);
								if (field.getAnnotation(Id.class) == null) {// 组织已存在时的更新子句
									fieldMeta.setId(false);
									generalFields.add(field);
									if (hasGeneralColumn) {
										sets.append(JDBCExecuteUtils.COMMA_SPACE);
									} else {
										hasGeneralColumn = true;
									}
									if (hardFieldSet.contains(field.getName())) {
										updateSetTemplate = getUpdateSetTemplate();
									} else {
										updateSetTemplate = getUpdateSetIfNotNullTemplate();
									}
									sets.append(PlaceHolderUtils.replace(updateSetTemplate, "columnName", columnName));
								} else {
									fieldMeta.setId(true);
									idFields.add(field);
									if (hasId) {
										condition.append(JDBCExecuteUtils.SPACE_AND_SPACE);
									} else {
										hasId = true;
									}
									condition.append(columnName).append(JDBCExecuteUtils.SPACE_EQ_SPACE)
											.append(SQLUtils.PARAM_MARK);
								}
								fieldMetas.add(fieldMeta);
							}
						}
					}
					current = current.getSuperclass();
				}
				entityMeta = new EntityMeta(EntityUtils.getTableName(type), fieldMetas);
				EntityUtils.cacheEntityMeta(type, entityMeta);
			} else {
				List fieldMetas = entityMeta.getFieldMetas();
				for (int i = 0, size = fieldMetas.size(); i < size; i++) {
					FieldMeta fieldMeta = fieldMetas.get(i);
					Field field = fieldMeta.getField();
					String columnName = fieldMeta.getColumnName();
					if (fieldMeta.isId()) {
						idFields.add(field);
						if (hasId) {
							condition.append(JDBCExecuteUtils.SPACE_AND_SPACE);
						} else {
							hasId = true;
						}
						condition.append(columnName).append(JDBCExecuteUtils.SPACE_EQ_SPACE).append(SQLUtils.PARAM_MARK);
					} else {// 组织已存在时的更新子句
						generalFields.add(field);
						if (hasGeneralColumn) {
							sets.append(JDBCExecuteUtils.COMMA_SPACE);
						} else {
							hasGeneralColumn = true;
						}
						if (hardFieldSet.contains(field.getName())) {
							updateSetTemplate = getUpdateSetTemplate();
						} else {
							updateSetTemplate = getUpdateSetIfNotNullTemplate();
						}
						sets.append(PlaceHolderUtils.replace(updateSetTemplate, "columnName", columnName));
					}
				}
			}
		} catch (IllegalArgumentException e) {
			throw new DataAccessException(e);
		}
		return updateSQL(type, hasId, hasGeneralColumn, entityMeta.getTableName(), sets, condition, generalFields,
				idFields);
	}

	@Override
	public  MergeSQL save(Class type) {
		EntityMeta entityMeta = EntityUtils.getCachedEntityMeta(type);
		boolean columnFound = false;
		Map templateParams = getSQLTemplateParams();
		try {
			if (entityMeta == null) {
				List fieldMetas = new ArrayList();
				columnFound = parse(type, templateParams, fieldMetas);
				entityMeta = new EntityMeta(EntityUtils.getTableName(type), fieldMetas);
				EntityUtils.cacheEntityMeta(type, entityMeta);
			} else {
				boolean setsFlag = false;
				StringBuilder sets = templateParams.get(SETS);
				List fieldMetas = entityMeta.getFieldMetas();
				for (int i = 0, size = fieldMetas.size(); i < size; i++) {
					FieldMeta fieldMeta = fieldMetas.get(i);
					String columnName = fieldMeta.getColumnName();
					if (columnFound) {
						appendComma(templateParams, getNeedsCommaParamNames());
					} else {
						columnFound = true;
					}
					handleColumnWhenSave(columnName, templateParams);
					if (fieldMeta.isId()) {
						handleIdColumnWhenSave(columnName, templateParams, setsFlag);
					} else {// 组织已存在时的更新子句
						if (setsFlag) {
							sets.append(JDBCExecuteUtils.COMMA_SPACE);
						} else {
							setsFlag = true;
						}
						appendSetIfNotNull(sets, columnName);
					}
				}
			}
		} catch (IllegalArgumentException | IllegalAccessException e) {
			throw new DataAccessException(e);
		}
		if (columnFound) {
			return mergeSql(entityMeta, templateParams);
		} else {
			throw new ColumnNotFoundException(
					String.format("Column not found in class %s, please use @Column to config fields", type.getName()));
		}
	}

	@Override
	public  MergeSQL save(Class type, String... hardFields) {
		Set hardFieldSet = new HashSet();
		for (int i = 0; i < hardFields.length; i++) {
			hardFieldSet.add(hardFields[i]);
		}
		boolean columnFound = false;
		EntityMeta entityMeta = EntityUtils.getCachedEntityMeta(type);
		Map templateParams = getSQLTemplateParams();
		try {
			if (entityMeta == null) {
				List fieldMetas = new ArrayList();
				columnFound = parse(type, templateParams, fieldMetas, hardFieldSet);
				entityMeta = new EntityMeta(EntityUtils.getTableName(type), fieldMetas);
				EntityUtils.cacheEntityMeta(type, entityMeta);
			} else {
				boolean setsFlag = false;
				StringBuilder sets = templateParams.get(SETS);
				List fieldMetas = entityMeta.getFieldMetas();
				for (int i = 0, size = fieldMetas.size(); i < size; i++) {
					FieldMeta fieldMeta = fieldMetas.get(i);
					String columnName = fieldMeta.getColumnName();
					Field field = fieldMeta.getField();
					if (columnFound) {
						appendComma(templateParams, getNeedsCommaParamNames());
					} else {
						columnFound = true;
					}
					handleColumnWhenSave(columnName, templateParams);
					if (fieldMeta.isId()) {
						handleIdColumnWhenSave(columnName, templateParams, setsFlag);
					} else {// 组织已存在时的更新子句
						if (setsFlag) {
							sets.append(JDBCExecuteUtils.COMMA_SPACE);
						} else {
							setsFlag = true;
						}
						if (hardFieldSet.contains(field.getName())) {
							appendSet(sets, columnName);
						} else {
							appendSetIfNotNull(sets, columnName);
						}
					}
				}
			}
		} catch (IllegalArgumentException | IllegalAccessException e) {
			throw new DataAccessException(e);
		}
		if (columnFound) {
			return mergeSql(entityMeta, templateParams);
		} else {
			throw new ColumnNotFoundException(
					String.format("Column not found in class %s, please use @Column to config fields", type.getName()));
		}
	}

	@Override
	public  MergeSQL hardSave(Class type) {
		EntityMeta entityMeta = EntityUtils.getCachedEntityMeta(type);
		boolean columnFound = false;
		Map templateParams = getSQLTemplateParams();
		try {
			if (entityMeta == null) {
				List fieldMetas = new ArrayList();
				columnFound = hardParse(type, templateParams, fieldMetas);
				entityMeta = new EntityMeta(EntityUtils.getTableName(type), fieldMetas);
				EntityUtils.cacheEntityMeta(type, entityMeta);
			} else {
				boolean setsFlag = false;
				StringBuilder sets = templateParams.get(SETS);
				List fieldMetas = entityMeta.getFieldMetas();
				for (int i = 0, size = fieldMetas.size(); i < size; i++) {
					FieldMeta fieldMeta = fieldMetas.get(i);
					String columnName = fieldMeta.getColumnName();
					if (columnFound) {
						appendComma(templateParams, getNeedsCommaParamNames());
					} else {
						columnFound = true;
					}
					handleColumnWhenSave(columnName, templateParams);
					if (fieldMeta.isId()) {
						handleIdColumnWhenSave(columnName, templateParams, setsFlag);
					} else {// 组织已存在时的更新子句
						if (setsFlag) {
							sets.append(JDBCExecuteUtils.COMMA_SPACE);
						} else {
							setsFlag = true;
						}
						appendSet(sets, columnName);
					}
				}
			}
		} catch (IllegalArgumentException | IllegalAccessException e) {
			throw new DataAccessException(e);
		}
		if (columnFound) {
			return mergeSql(entityMeta, templateParams);
		} else {
			throw new ColumnNotFoundException(
					String.format("Column not found in class %s, please use @Column to config fields", type.getName()));
		}
	}

	@Override
	public  SQL update(T obj) {
		Class type = obj.getClass();
		EntityMeta entityMeta = EntityUtils.getCachedEntityMeta(type);
		boolean hasId = false, hasGeneralColumn = false;
		StringBuilder sets = new StringBuilder(), condition = new StringBuilder();
		List values = new ArrayList(), conditionValues = new ArrayList();
		try {
			if (entityMeta == null) {
				Class current = type;
				Set fieldSet = new HashSet();
				List fieldMetas = new ArrayList();
				while (!Object.class.equals(current)) {
					Field[] declaredFields = current.getDeclaredFields();
					for (int i = 0; i < declaredFields.length; i++) {
						Field field = declaredFields[i];
						String fieldName = field.getName();
						if (!fieldSet.contains(fieldName)) {
							fieldSet.add(fieldName);
							Column column = field.getAnnotation(Column.class);
							if (column != null) {
								field.setAccessible(true);
								String columnName = column.name();
								if (StringUtils.isBlank(columnName)) {
									columnName = StringUtils.camelToUnderline(fieldName, true);
								}
								FieldMeta fieldMeta = new FieldMeta(field, columnName);
								Object param = field.get(obj);
								if (field.getAnnotation(Id.class) == null) {// 组织已存在时的更新子句
									fieldMeta.setId(false);
									if (param != null) {
										values.add(param);
										if (hasGeneralColumn) {
											sets.append(JDBCExecuteUtils.COMMA_SPACE);
										} else {
											hasGeneralColumn = true;
										}
										sets.append(PlaceHolderUtils.replace(getUpdateSetTemplate(), "columnName",
												columnName));
									}
								} else {
									fieldMeta.setId(true);
									conditionValues.add(param);
									if (hasId) {
										condition.append(JDBCExecuteUtils.SPACE_AND_SPACE);
									} else {
										hasId = true;
									}
									condition.append(columnName).append(JDBCExecuteUtils.SPACE_EQ_SPACE)
											.append(SQLUtils.PARAM_MARK);
								}
								fieldMetas.add(fieldMeta);
							}
						}
					}
					current = current.getSuperclass();
				}
				entityMeta = new EntityMeta(EntityUtils.getTableName(type), fieldMetas);
				EntityUtils.cacheEntityMeta(type, entityMeta);
			} else {
				List fieldMetas = entityMeta.getFieldMetas();
				for (int i = 0, size = fieldMetas.size(); i < size; i++) {
					FieldMeta fieldMeta = fieldMetas.get(i);
					Field field = fieldMeta.getField();
					String columnName = fieldMeta.getColumnName();
					Object param = field.get(obj);
					if (fieldMeta.isId()) {
						conditionValues.add(param);
						if (hasId) {
							condition.append(JDBCExecuteUtils.SPACE_AND_SPACE);
						} else {
							hasId = true;
						}
						condition.append(columnName).append(JDBCExecuteUtils.SPACE_EQ_SPACE).append(SQLUtils.PARAM_MARK);
					} else {// 组织已存在时的更新子句
						if (param != null) {
							values.add(param);
							if (hasGeneralColumn) {
								sets.append(JDBCExecuteUtils.COMMA_SPACE);
							} else {
								hasGeneralColumn = true;
							}
							sets.append(PlaceHolderUtils.replace(getUpdateSetTemplate(), "columnName", columnName));
						}
					}
				}
			}
		} catch (IllegalArgumentException | IllegalAccessException e) {
			throw new DataAccessException(e);
		}
		return sql(obj, hasId, hasGeneralColumn, entityMeta.getTableName(), sets, condition, values, conditionValues);
	}

	@Override
	public  SQL update(T obj, String... hardFields) {
		Set hardFieldSet = new HashSet();
		for (int i = 0; i < hardFields.length; i++) {
			hardFieldSet.add(hardFields[i]);
		}
		Class type = obj.getClass();
		EntityMeta entityMeta = EntityUtils.getCachedEntityMeta(type);
		boolean hasId = false, hasGeneralColumn = false;
		StringBuilder sets = new StringBuilder(), condition = new StringBuilder();
		List values = new ArrayList(), conditionValues = new ArrayList();
		try {
			if (entityMeta == null) {
				Class current = type;
				Set fieldSet = new HashSet();
				List fieldMetas = new ArrayList();
				while (!Object.class.equals(current)) {
					Field[] declaredFields = current.getDeclaredFields();
					for (int i = 0; i < declaredFields.length; i++) {
						Field field = declaredFields[i];
						String fieldName = field.getName();
						if (!fieldSet.contains(fieldName)) {
							fieldSet.add(fieldName);
							Column column = field.getAnnotation(Column.class);
							if (column != null) {
								field.setAccessible(true);
								String columnName = column.name();
								if (StringUtils.isBlank(columnName)) {
									columnName = StringUtils.camelToUnderline(fieldName, true);
								}
								FieldMeta fieldMeta = new FieldMeta(field, columnName);
								Object param = field.get(obj);
								if (field.getAnnotation(Id.class) == null) {// 组织已存在时的更新子句
									fieldMeta.setId(false);
									if (param != null || hardFieldSet.contains(field.getName())) {
										values.add(param);
										if (hasGeneralColumn) {
											sets.append(JDBCExecuteUtils.COMMA_SPACE);
										} else {
											hasGeneralColumn = true;
										}
										sets.append(PlaceHolderUtils.replace(getUpdateSetTemplate(), "columnName",
												columnName));
									}
								} else {
									fieldMeta.setId(true);
									conditionValues.add(param);
									if (hasId) {
										condition.append(JDBCExecuteUtils.SPACE_AND_SPACE);
									} else {
										hasId = true;
									}
									condition.append(columnName).append(JDBCExecuteUtils.SPACE_EQ_SPACE)
											.append(SQLUtils.PARAM_MARK);
								}
								fieldMetas.add(fieldMeta);
							}
						}
					}
					current = current.getSuperclass();
				}
				entityMeta = new EntityMeta(EntityUtils.getTableName(type), fieldMetas);
				EntityUtils.cacheEntityMeta(type, entityMeta);
			} else {
				List fieldMetas = entityMeta.getFieldMetas();
				for (int i = 0, size = fieldMetas.size(); i < size; i++) {
					FieldMeta fieldMeta = fieldMetas.get(i);
					Field field = fieldMeta.getField();
					String columnName = fieldMeta.getColumnName();
					Object param = field.get(obj);
					if (fieldMeta.isId()) {
						conditionValues.add(param);
						if (hasId) {
							condition.append(JDBCExecuteUtils.SPACE_AND_SPACE);
						} else {
							hasId = true;
						}
						condition.append(columnName).append(JDBCExecuteUtils.SPACE_EQ_SPACE).append(SQLUtils.PARAM_MARK);
					} else {// 组织已存在时的更新子句
						if (param != null || hardFieldSet.contains(field.getName())) {
							values.add(param);
							if (hasGeneralColumn) {
								sets.append(JDBCExecuteUtils.COMMA_SPACE);
							} else {
								hasGeneralColumn = true;
							}
							sets.append(PlaceHolderUtils.replace(getUpdateSetTemplate(), "columnName", columnName));
						}
					}
				}
			}
		} catch (IllegalArgumentException | IllegalAccessException e) {
			throw new DataAccessException(e);
		}
		return sql(obj, hasId, hasGeneralColumn, entityMeta.getTableName(), sets, condition, values, conditionValues);
	}

	@Override
	public  SQL save(T obj) {
		Class type = obj.getClass();
		EntityMeta entityMeta = EntityUtils.getCachedEntityMeta(type);
		boolean columnFound = false;
		List params = new ArrayList();
		Map templateParams = getSQLTemplateParams();
		try {
			if (entityMeta == null) {
				List fieldMetas = new ArrayList();
				columnFound = parse(obj, templateParams, params, fieldMetas);
				entityMeta = new EntityMeta(EntityUtils.getTableName(type), fieldMetas);
				EntityUtils.cacheEntityMeta(type, entityMeta);
			} else {
				boolean setsFlag = false;
				List fieldMetas = entityMeta.getFieldMetas();
				StringBuilder sets = templateParams.get(SETS);
				for (int i = 0, size = fieldMetas.size(); i < size; i++) {
					FieldMeta fieldMeta = fieldMetas.get(i);
					String columnName = fieldMeta.getColumnName();
					Object param = fieldMeta.getField().get(obj);
					if (param != null) {// 仅插入非NULL部分的字段值
						params.add(param);
						if (columnFound) {
							appendComma(templateParams, getNeedsCommaParamNames());
						} else {
							columnFound = true;
						}
						handleColumnWhenSave(columnName, templateParams);
						if (fieldMeta.isId()) {
							handleIdColumnWhenSave(columnName, templateParams, setsFlag);
						} else {// 组织已存在时的更新子句
							if (setsFlag) {
								sets.append(JDBCExecuteUtils.COMMA_SPACE);
							} else {
								setsFlag = true;
							}
							appendSet(sets, columnName);
						}
					}
				}
			}
		} catch (IllegalArgumentException | IllegalAccessException e) {
			throw new DataAccessException(e);
		}
		if (columnFound) {
			return sql(entityMeta.getTableName(), templateParams, params);
		} else {
			throw new ColumnNotFoundException(String.format(
					"Not null column not found in class %s, please use @Column to config fields and make sure at lease one of them is not null",
					type.getName()));
		}
	}

	@Override
	public  SQL save(T obj, String... hardFields) {
		Set hardFieldSet = new HashSet();
		for (int i = 0; i < hardFields.length; i++) {
			hardFieldSet.add(hardFields[i]);
		}
		Class type = obj.getClass();
		EntityMeta entityMeta = EntityUtils.getCachedEntityMeta(type);
		boolean columnFound = false;
		List params = new ArrayList();
		Map templateParams = getSQLTemplateParams();
		try {
			if (entityMeta == null) {
				List fieldMetas = new ArrayList();
				columnFound = parse(obj, templateParams, params, fieldMetas, hardFieldSet);
				entityMeta = new EntityMeta(EntityUtils.getTableName(type), fieldMetas);
				EntityUtils.cacheEntityMeta(type, entityMeta);
			} else {
				boolean setsFlag = false;
				List fieldMetas = entityMeta.getFieldMetas();
				StringBuilder sets = templateParams.get(SETS);
				for (int i = 0, size = fieldMetas.size(); i < size; i++) {
					FieldMeta fieldMeta = fieldMetas.get(i);
					String columnName = fieldMeta.getColumnName();
					Field field = fieldMeta.getField();
					Object param = field.get(obj);
					if (param != null || hardFieldSet.contains(field.getName())) {// 仅插入非NULL或硬保存部分的字段值
						params.add(param);
						if (columnFound) {
							appendComma(templateParams, getNeedsCommaParamNames());
						} else {
							columnFound = true;
						}
						handleColumnWhenSave(columnName, templateParams);
						if (fieldMeta.isId()) {
							handleIdColumnWhenSave(columnName, templateParams, setsFlag);
						} else {// 组织已存在时的更新子句
							if (setsFlag) {
								sets.append(JDBCExecuteUtils.COMMA_SPACE);
							} else {
								setsFlag = true;
							}
							appendSet(sets, columnName);
						}
					}
				}
			}
		} catch (IllegalArgumentException | IllegalAccessException e) {
			throw new DataAccessException(e);
		}
		if (columnFound) {
			return sql(entityMeta.getTableName(), templateParams, params);
		} else {
			throw new ColumnNotFoundException(String.format(
					"Not null or hard save column not found in class %s, please use @Column to config fields and make sure at lease one of them is not null or hard save",
					type.getName()));
		}
	}

	@Override
	public  SQL hardSave(T obj) {
		Class type = obj.getClass();
		EntityMeta entityMeta = EntityUtils.getCachedEntityMeta(type);
		boolean columnFound = false;
		List params = new ArrayList();
		Map templateParams = getSQLTemplateParams();
		try {
			if (entityMeta == null) {
				List fieldMetas = new ArrayList();
				columnFound = hardParse(obj, templateParams, params, fieldMetas);
				entityMeta = new EntityMeta(EntityUtils.getTableName(type), fieldMetas);
				EntityUtils.cacheEntityMeta(type, entityMeta);
			} else {
				boolean setsFlag = false;
				List fieldMetas = entityMeta.getFieldMetas();
				StringBuilder sets = templateParams.get(SETS);
				for (int i = 0, size = fieldMetas.size(); i < size; i++) {
					FieldMeta fieldMeta = fieldMetas.get(i);
					String columnName = fieldMeta.getColumnName();
					Field field = fieldMeta.getField();
					params.add(field.get(obj));
					if (columnFound) {
						appendComma(templateParams, getNeedsCommaParamNames());
					} else {
						columnFound = true;
					}
					handleColumnWhenSave(columnName, templateParams);
					if (fieldMeta.isId()) {
						handleIdColumnWhenSave(columnName, templateParams, setsFlag);
					} else {// 组织已存在时的更新子句
						if (setsFlag) {
							sets.append(JDBCExecuteUtils.COMMA_SPACE);
						} else {
							setsFlag = true;
						}
						appendSet(sets, columnName);
					}
				}
			}
		} catch (IllegalArgumentException | IllegalAccessException e) {
			throw new DataAccessException(e);
		}
		if (columnFound) {
			return sql(entityMeta.getTableName(), templateParams, params);
		} else {
			throw new ColumnNotFoundException(
					String.format("Column not found in class %s, please use @Column to config fields", type.getName()));
		}
	}

	@Override
	public String pageSql(Connection con, String sql, Map params, SQLMetaData sqlMetaData, int pageSize,
			long currentPage) throws SQLException {
		return getSQLPagingDialect().pageSql(con, sql, params, sqlMetaData, pageSize, currentPage);
	}

	private  UpdateSQL updateSQL(Class type, boolean hasId, boolean hasGeneralColumn, String tableName,
			StringBuilder sets, StringBuilder condition, List generalFields, List idFields) {
		if (hasId) {
			if (hasGeneralColumn) {
				generalFields.addAll(idFields);
				return new UpdateSQL(
						PlaceHolderUtils.replace(UPDATE, "tableName", tableName, "sets", sets, "condition", condition),
						generalFields);
			} else {
				throw new NoColumnForUpdateException(String.format(
						"There is only id column(s), but no general column found in class %s, please check your config",
						type.getName()));
			}
		} else {
			throw new PkNotFoundException(
					"Primary key not found in class ".concat(type.getName()).concat(", please use @Id to config"));
		}
	}

	private  boolean parse(Class type, Map templateParams, List fieldMetas)
			throws IllegalArgumentException, IllegalAccessException {
		boolean flag = false, setsFlag = false;
		Class current = type;
		Set fieldSet = new HashSet();
		StringBuilder sets = templateParams.get(SETS);
		while (!Object.class.equals(current)) {
			Field[] declaredFields = current.getDeclaredFields();
			for (int i = 0; i < declaredFields.length; i++) {
				Field field = declaredFields[i];
				String fieldName = field.getName();
				if (!fieldSet.contains(fieldName)) {
					fieldSet.add(fieldName);
					Column column = field.getAnnotation(Column.class);
					if (column != null) {
						field.setAccessible(true);
						String columnName = column.name();
						if (StringUtils.isBlank(columnName)) {
							columnName = StringUtils.camelToUnderline(fieldName, true);
						}
						FieldMeta fieldMeta = new FieldMeta(field, columnName);
						if (flag) {
							appendComma(templateParams, getNeedsCommaParamNames());
						} else {
							flag = true;
						}
						handleColumnWhenSave(columnName, templateParams);
						if (field.getAnnotation(Id.class) == null) {// 组织已存在时的更新子句
							fieldMeta.setId(false);
							if (setsFlag) {
								sets.append(JDBCExecuteUtils.COMMA_SPACE);
							} else {
								setsFlag = true;
							}
							appendSetIfNotNull(sets, columnName);
						} else {
							fieldMeta.setId(true);
							handleIdColumnWhenSave(columnName, templateParams, setsFlag);
						}
						fieldMetas.add(fieldMeta);
					}
				}
			}
			current = current.getSuperclass();
		}
		return flag;
	}

	private  boolean parse(Class type, Map templateParams, List fieldMetas,
			Set hardFieldSet) throws IllegalArgumentException, IllegalAccessException {
		boolean flag = false, setsFlag = false;
		Class current = type;
		Set fieldSet = new HashSet();
		StringBuilder sets = templateParams.get(SETS);
		while (!Object.class.equals(current)) {
			Field[] declaredFields = current.getDeclaredFields();
			for (int i = 0; i < declaredFields.length; i++) {
				Field field = declaredFields[i];
				String fieldName = field.getName();
				if (!fieldSet.contains(fieldName)) {
					fieldSet.add(fieldName);
					Column column = field.getAnnotation(Column.class);
					if (column != null) {
						field.setAccessible(true);
						String columnName = column.name();
						if (StringUtils.isBlank(columnName)) {
							columnName = StringUtils.camelToUnderline(fieldName, true);
						}
						FieldMeta fieldMeta = new FieldMeta(field, columnName);
						if (flag) {
							appendComma(templateParams, getNeedsCommaParamNames());
						} else {
							flag = true;
						}
						handleColumnWhenSave(columnName, templateParams);
						if (field.getAnnotation(Id.class) == null) {// 组织已存在时的更新子句
							fieldMeta.setId(false);
							sets = templateParams.get(SETS);
							if (setsFlag) {
								sets.append(JDBCExecuteUtils.COMMA_SPACE);
							} else {
								setsFlag = true;
							}
							if (hardFieldSet.contains(field.getName())) {
								appendSet(sets, columnName);
							} else {
								appendSetIfNotNull(sets, columnName);
							}
						} else {
							fieldMeta.setId(true);
							handleIdColumnWhenSave(columnName, templateParams, setsFlag);
						}
						fieldMetas.add(fieldMeta);
					}
				}
			}
			current = current.getSuperclass();
		}
		return flag;
	}

	private  boolean hardParse(Class type, Map templateParams, List fieldMetas)
			throws IllegalArgumentException, IllegalAccessException {
		boolean flag = false, setsFlag = false;
		Class current = type;
		Set fieldSet = new HashSet();
		StringBuilder sets = templateParams.get(SETS);
		while (!Object.class.equals(current)) {
			Field[] declaredFields = current.getDeclaredFields();
			for (int i = 0; i < declaredFields.length; i++) {
				Field field = declaredFields[i];
				String fieldName = field.getName();
				if (!fieldSet.contains(fieldName)) {
					fieldSet.add(fieldName);
					Column column = field.getAnnotation(Column.class);
					if (column != null) {
						field.setAccessible(true);
						String columnName = column.name();
						if (StringUtils.isBlank(columnName)) {
							columnName = StringUtils.camelToUnderline(fieldName, true);
						}
						FieldMeta fieldMeta = new FieldMeta(field, columnName);
						if (flag) {
							appendComma(templateParams, getNeedsCommaParamNames());
						} else {
							flag = true;
						}
						handleColumnWhenSave(columnName, templateParams);
						if (field.getAnnotation(Id.class) == null) {// 组织已存在时的更新子句
							fieldMeta.setId(false);
							if (setsFlag) {
								sets.append(JDBCExecuteUtils.COMMA_SPACE);
							} else {
								setsFlag = true;
							}
							appendSet(sets, columnName);
						} else {
							fieldMeta.setId(true);
							handleIdColumnWhenSave(columnName, templateParams, setsFlag);
						}
						fieldMetas.add(fieldMeta);
					}
				}
			}
			current = current.getSuperclass();
		}
		return flag;
	}

	private  boolean parse(T obj, Map templateParams, List params,
			List fieldMetas) throws IllegalArgumentException, IllegalAccessException {
		boolean flag = false, setsFlag = false;
		Class current = obj.getClass();
		Set fieldSet = new HashSet();
		StringBuilder sets = templateParams.get(SETS);
		while (!Object.class.equals(current)) {
			Field[] declaredFields = current.getDeclaredFields();
			for (int i = 0; i < declaredFields.length; i++) {
				Field field = declaredFields[i];
				String fieldName = field.getName();
				if (!fieldSet.contains(fieldName)) {
					fieldSet.add(fieldName);
					Column column = field.getAnnotation(Column.class);
					if (column != null) {
						field.setAccessible(true);
						String columnName = column.name();
						if (StringUtils.isBlank(columnName)) {
							columnName = StringUtils.camelToUnderline(fieldName, true);
						}
						FieldMeta fieldMeta = new FieldMeta(field, columnName);
						Object param = field.get(obj);
						if (param != null) {// 仅插入非NULL部分的字段值
							params.add(param);
							if (flag) {
								appendComma(templateParams, getNeedsCommaParamNames());
							} else {
								flag = true;
							}
							handleColumnWhenSave(columnName, templateParams);
							if (field.getAnnotation(Id.class) == null) {// 组织已存在时的更新子句
								fieldMeta.setId(false);
								if (setsFlag) {
									sets.append(JDBCExecuteUtils.COMMA_SPACE);
								} else {
									setsFlag = true;
								}
								appendSet(sets, columnName);
							} else {
								fieldMeta.setId(true);
								handleIdColumnWhenSave(columnName, templateParams, setsFlag);
							}
						}
						fieldMetas.add(fieldMeta);
					}
				}
			}
			current = current.getSuperclass();
		}
		return flag;
	}

	private  boolean parse(T obj, Map templateParams, List params,
			List fieldMetas, Set hardFieldSet)
			throws IllegalArgumentException, IllegalAccessException {
		boolean flag = false, setsFlag = false;
		Class current = obj.getClass();
		Map fieldMap = new HashMap();
		StringBuilder sets = templateParams.get(SETS);
		while (!Object.class.equals(current)) {
			Field[] declaredFields = current.getDeclaredFields();
			for (int i = 0; i < declaredFields.length; i++) {
				Field field = declaredFields[i];
				String fieldName = field.getName();
				if (!fieldMap.containsKey(fieldName)) {
					fieldMap.put(fieldName, Boolean.TRUE);
					Column column = field.getAnnotation(Column.class);
					if (column != null) {
						field.setAccessible(true);
						String columnName = column.name();
						if (StringUtils.isBlank(columnName)) {
							columnName = StringUtils.camelToUnderline(fieldName, true);
						}
						FieldMeta fieldMeta = new FieldMeta(field, columnName);
						Object param = field.get(obj);
						if (param != null || hardFieldSet.contains(field.getName())) {// 仅插入非NULL或硬保存部分的字段值
							params.add(param);
							if (flag) {
								appendComma(templateParams, getNeedsCommaParamNames());
							} else {
								flag = true;
							}
							handleColumnWhenSave(columnName, templateParams);
							if (field.getAnnotation(Id.class) == null) {// 组织已存在时的更新子句
								fieldMeta.setId(false);
								if (setsFlag) {
									sets.append(JDBCExecuteUtils.COMMA_SPACE);
								} else {
									setsFlag = true;
								}
								appendSet(sets, columnName);
							} else {
								fieldMeta.setId(true);
								handleIdColumnWhenSave(columnName, templateParams, setsFlag);
							}
						}
						fieldMetas.add(fieldMeta);
					}
				}
			}
			current = current.getSuperclass();
		}
		return flag;
	}

	private  boolean hardParse(T obj, Map templateParams, List params,
			List fieldMetas) throws IllegalArgumentException, IllegalAccessException {
		boolean flag = false, setsFlag = false;
		Class current = obj.getClass();
		Map fieldMap = new HashMap();
		StringBuilder sets = templateParams.get(SETS);
		while (!Object.class.equals(current)) {
			Field[] declaredFields = current.getDeclaredFields();
			for (int i = 0; i < declaredFields.length; i++) {
				Field field = declaredFields[i];
				String fieldName = field.getName();
				if (!fieldMap.containsKey(fieldName)) {
					fieldMap.put(fieldName, Boolean.TRUE);
					Column column = field.getAnnotation(Column.class);
					if (column != null) {
						field.setAccessible(true);
						String columnName = column.name();
						if (StringUtils.isBlank(columnName)) {
							columnName = StringUtils.camelToUnderline(fieldName, true);
						}
						FieldMeta fieldMeta = new FieldMeta(field, columnName);
						params.add(field.get(obj));
						if (flag) {
							appendComma(templateParams, getNeedsCommaParamNames());
						} else {
							flag = true;
						}
						handleColumnWhenSave(columnName, templateParams);
						if (field.getAnnotation(Id.class) == null) {// 组织已存在时的更新子句
							fieldMeta.setId(false);
							if (setsFlag) {
								sets.append(JDBCExecuteUtils.COMMA_SPACE);
							} else {
								setsFlag = true;
							}
							appendSet(sets, columnName);
						} else {
							fieldMeta.setId(true);
							handleIdColumnWhenSave(columnName, templateParams, setsFlag);
						}
						fieldMetas.add(fieldMeta);
					}
				}
			}
			current = current.getSuperclass();
		}
		return flag;
	}

	/**
	 * 获取SQL模板参数集
	 * 
	 * @return 返回SQL模板参数集
	 */
	private Map getSQLTemplateParams() {
		Map params = new HashMap();
		params.put(COLUMNS, new StringBuilder());
		params.put(VALUES, new StringBuilder());
		params.put(SETS, new StringBuilder());
		List paramNames = getExtSQLTemplateParamNames();
		if (paramNames != null) {
			for (int i = 0, size = paramNames.size(); i < size; i++) {
				params.put(paramNames.get(i), new StringBuilder());
			}
		}
		return params;
	}

	private void appendSet(StringBuilder sets, String columnName) {
		sets.append(PlaceHolderUtils.replace(getSetTemplate(), "columnName", columnName));
	}

	private void appendSetIfNotNull(StringBuilder sets, String columnName) {
		sets.append(PlaceHolderUtils.replace(getSetIfNotNullTemplate(), "columnName", columnName));
	}

	/**
	 * 向参数集指定参数追加逗号
	 * 
	 * @param params
	 *            参数集
	 * @param paramNames
	 *            参数名
	 */
	private static final void appendComma(Map params, List paramNames) {
		for (int i = 0, size = paramNames.size(); i < size; i++) {
			params.get(paramNames.get(i)).append(JDBCExecuteUtils.COMMA_SPACE);
		}
	}

	private MergeSQL mergeSql(EntityMeta entityMeta, Map templateParams) {
		templateParams.put(TABLE_NAME, new StringBuilder(entityMeta.getTableName()));
		if (templateParams.get(SETS).length() > 0) {
			return new MergeSQL(PlaceHolderUtils.replace(getSaveSQLTemplate(), templateParams),
					entityMeta.getFieldMetas());
		} else {
			return new MergeSQL(PlaceHolderUtils.replace(getInsertIfNotExistsSQLTemplate(), templateParams),
					entityMeta.getFieldMetas());
		}
	}

	private  SQL sql(T obj, boolean hasId, boolean hasGeneralColumn, String tableName, StringBuilder sets,
			StringBuilder condition, List values, List conditionValues) {
		if (hasId) {
			if (hasGeneralColumn) {
				values.addAll(conditionValues);
				return new SQL(
						PlaceHolderUtils.replace(UPDATE, "tableName", tableName, "sets", sets, "condition", condition),
						values);
			} else {
				throw new NoColumnForUpdateException(String.format(
						"There is only id column(s), but no general column witch is not null found in object %s, please check your config and field value",
						obj.toString()));
			}
		} else {
			throw new PkNotFoundException("Primary key not found in class ".concat(obj.getClass().getName())
					.concat(", please use @Id to config"));
		}
	}

	private SQL sql(String tableName, Map templateParams, List params) {
		templateParams.put(TABLE_NAME, new StringBuilder(tableName));
		if (templateParams.get(SETS).length() > 0) {
			return new SQL(PlaceHolderUtils.replace(getSaveSQLTemplate(), templateParams), params);
		} else {
			return new SQL(PlaceHolderUtils.replace(getInsertIfNotExistsSQLTemplate(), templateParams), params);
		}
	}

}