package org.nutz.dao.util; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.sql.DataSource; import org.nutz.dao.Chain; import org.nutz.dao.Condition; import org.nutz.dao.ConnCallback; import org.nutz.dao.Dao; import org.nutz.dao.DaoException; import org.nutz.dao.FieldFilter; import org.nutz.dao.FieldMatcher; import org.nutz.dao.Sqls; import org.nutz.dao.TableName; import org.nutz.dao.entity.Entity; import org.nutz.dao.entity.EntityIndex; import org.nutz.dao.entity.LinkField; import org.nutz.dao.entity.MappingField; import org.nutz.dao.entity.annotation.Table; import org.nutz.dao.impl.NutDao; import org.nutz.dao.impl.entity.field.ManyManyLinkField; import org.nutz.dao.impl.sql.SqlFormat; import org.nutz.dao.jdbc.JdbcExpert; import org.nutz.dao.jdbc.Jdbcs; import org.nutz.dao.jdbc.ValueAdaptor; import org.nutz.dao.pager.Pager; import org.nutz.dao.sql.Sql; import org.nutz.dao.sql.SqlCallback; import org.nutz.lang.Lang; import org.nutz.lang.Strings; import org.nutz.lang.random.R; import org.nutz.lang.util.Callback2; import org.nutz.log.Log; import org.nutz.log.Logs; import org.nutz.resource.Scans; import org.nutz.trans.Molecule; import org.nutz.trans.Trans; /** * Dao 的帮助函数 * * @author zozoh(zozohtnt@gmail.com) * @author wendal(wendal1985@gmail.com) * @author cqyunqin * @author rekoe(koukou890@qq.com) */ public abstract class Daos { private static final Log log = Logs.get(); /** * 安全关闭Statement和ResultSet * * @param stat * Statement实例,可以为null * @param rs * ResultSet实例,可以为null */ public static void safeClose(Statement stat, ResultSet rs) { safeClose(rs); safeClose(stat); } /** * 安全关闭Statement * * @param stat * Statement实例,可以为null */ public static void safeClose(Statement stat) { if (null != stat) try { stat.close(); } catch (Throwable e) {} } /** * 安全关闭=ResultSet * * @param rs * ResultSet实例,可以为null */ public static void safeClose(ResultSet rs) { if (null != rs) try { rs.close(); } catch (Throwable e) {} } /** * 获取colName所在的行数 * * @param meta * 从连接中取出的ResultSetMetaData * @param colName * 字段名 * @return 所在的索引,如果不存在就抛出异常 * @throws SQLException * 指定的colName找不到 */ public static int getColumnIndex(ResultSetMetaData meta, String colName) throws SQLException { if (meta == null) return 0; int columnCount = meta.getColumnCount(); for (int i = 1; i <= columnCount; i++) if (meta.getColumnName(i).equalsIgnoreCase(colName)) return i; // TODO 尝试一下meta.getColumnLabel? log.infof("Can not find @Column(%s) in table/view (%s)", colName, meta.getTableName(1)); throw Lang.makeThrow(SQLException.class, "Can not find @Column(%s)", colName); } /** * 是不是数值字段 * * @param meta * 从连接中取出的ResultSetMetaData * @param index * 字段索引 * @return 如果是就返回true * @throws SQLException * 指定的索引不存在 */ public static boolean isIntLikeColumn(ResultSetMetaData meta, int index) throws SQLException { switch (meta.getColumnType(index)) { case Types.BIGINT: case Types.INTEGER: case Types.SMALLINT: case Types.TINYINT: case Types.NUMERIC: return true; } return false; } /** * 填充记录总数 * * @param pager * 分页对象,如果为null就不进行任何操作 * @param dao * Dao实例 * @param entityType * 实体类,可以通过dao.getEntity获取 * @param cnd * 查询条件 * @return 传入的Pager参数 */ public static Pager updatePagerCount(Pager pager, Dao dao, Class<?> entityType, Condition cnd) { if (null != pager) { pager.setRecordCount(dao.count(entityType, cnd)); } return pager; } /** * 填充记录总数 * * @param pager * 分页对象,如果为null就不进行任何操作 * @param dao * Dao实例 * @param tableName * 表名 * @param cnd * 查询条件 * @return 传入的Pager参数 */ public static Pager updatePagerCount(Pager pager, Dao dao, String tableName, Condition cnd) { if (null != pager) { pager.setRecordCount(dao.count(tableName, cnd)); } return pager; } /** * 根据sql查询特定的记录,并转化为指定的类对象 * * @param dao * Dao实例 * @param klass * Pojo类 * @param sql_str * sql语句 * @return 查询结果 */ public static <T> List<T> queryList(Dao dao, Class<T> klass, String sql_str) { Sql sql = Sqls.create(sql_str) .setCallback(Sqls.callback.entities()) .setEntity(dao.getEntity(klass)); dao.execute(sql); return sql.getList(klass); } /** * 执行sql和callback * * @param dao * Dao实例 * @param sql_str * sql语句 * @param callback * sql回调 * @return 回调的返回值 */ public static Object query(Dao dao, String sql_str, SqlCallback callback) { Sql sql = Sqls.create(sql_str).setCallback(callback); dao.execute(sql); return sql.getResult(); } /** * 在同一个事务内查询对象及关联对象 * * @param dao * Dao实例 * @param classOfT * 指定的Pojo类 * @param cnd * 查询条件 * @param pager * 分页语句 * @param regex * 需要查出的关联对象, 可以参阅dao.fetchLinks * @return 查询结果 */ public static <T> List<T> queryWithLinks(final Dao dao, final Class<T> classOfT, final Condition cnd, final Pager pager, final String regex) { Molecule<List<T>> molecule = new Molecule<List<T>>() { public void run() { List<T> list = dao.query(classOfT, cnd, pager); dao.fetchLinks(list, regex); setObj(list); } }; return Trans.exec(molecule); } public static StringBuilder dataDict(DataSource ds, String... packages) { return dataDict(new NutDao(ds), packages); } /** 根据Pojo生成数据字典,zdoc格式 */ public static StringBuilder dataDict(Dao dao, String... packages) { StringBuilder sb = new StringBuilder(); List<Class<?>> ks = new ArrayList<Class<?>>(); for (String packageName : packages) { ks.addAll(Scans.me().scanPackage(packageName)); } Iterator<Class<?>> it = ks.iterator(); while (it.hasNext()) { Class<?> klass = it.next(); if (klass.getAnnotation(Table.class) == null) it.remove(); } // log.infof("Found %d table class", ks.size()); JdbcExpert exp = dao.getJdbcExpert(); Entity<?> entity = null; String line = "-------------------------------------------------------------------\n"; sb.append("#title:数据字典\n"); sb.append("#author:wendal\n"); sb.append("#index:0,1\n").append(line); for (Class<?> klass : ks) { sb.append(line); entity = dao.getEntity(klass); sb.append("表名 ").append(entity.getTableName()).append("\n\n"); if (!Strings.isBlank(entity.getTableComment())) sb.append("表注释: ").append(entity.getTableComment()); sb.append("\t").append("Java类名 ").append(klass.getName()).append("\n\n"); sb.append("\t||序号||列名||数据类型||主键||非空||默认值||java属性名||java类型||注释||\n"); int index = 1; for (MappingField field : entity.getMappingFields()) { String dataType = exp.evalFieldType(field); sb.append("\t||") .append(index++) .append("||") .append(field.getColumnName()) .append("||") .append(dataType) .append("||") .append(field.isPk()) .append("||") .append(field.isNotNull()) .append("||") .append(field.getDefaultValue(null) == null ? " " : field.getDefaultValue(null)) .append("||") .append(field.getName()) .append("||") .append(field.getTypeClass().getName()) .append("||") .append(field.getColumnComment() == null ? " " : field.getColumnComment()) .append("||\n"); } } return sb; } /** * 查询sql并把结果放入传入的class组成的List中 */ public static <T> List<T> query(Dao dao, Class<T> classOfT, String sql, Condition cnd, Pager pager) { Sql sql2 = Sqls.queryEntity(sql); sql2.setEntity(dao.getEntity(classOfT)); sql2.setCondition(cnd); sql2.setPager(pager); dao.execute(sql2); return sql2.getList(classOfT); } /** * 查询某sql的结果条数. 请使用Sql接口的版本 */ @Deprecated public static long queryCount(Dao dao, String sql) { String tmpTable = "as _nutz_tmp"; if (dao.meta().isDB2()) tmpTable = "as nutz_tmp_" + R.UU32(); else if (dao.meta().isOracle()) tmpTable = ""; else tmpTable += "_" + R.UU32(); Sql sql2 = Sqls.fetchLong("select count(1) from (" + sql + ")" + tmpTable); dao.execute(sql2); return sql2.getLong(); } /** * 查询某sql的结果条数 * @param dao 用于执行该count方法的dao实例 * @param sql 原本的Sql对象,将复制其sql语句,变量和参数表. */ public static long queryCount(Dao dao, Sql sql) { String tmpTable = "as _nutz_tmp"; if (dao.meta().isDB2()) tmpTable = "as nutz_tmp_" + R.UU32(); else if (dao.meta().isOracle()) tmpTable = ""; else tmpTable += "_" + R.UU32(); Sql sql2 = Sqls.fetchLong("select count(1) from (" + sql.getSourceSql() + ")" + tmpTable); for (String key : sql.params().keys()) { sql2.setParam(key, sql.params().get(key)); } for (String key : sql.vars().keys()) { sql2.setVar(key, sql.vars().get(key)); } return dao.execute(sql2).getLong(); } /** * 执行一个特殊的Chain(事实上普通Chain也能执行,但不建议使用) * * @see org.nutz.dao.Chain#addSpecial(String, Object) */ @SuppressWarnings({"rawtypes"}) public static void insertBySpecialChain(Dao dao, Entity en, String tableName, Chain chain) { if (en != null) tableName = en.getTableName(); if (tableName == null) throw Lang.makeThrow(DaoException.class, "tableName and en is NULL !!"); final StringBuilder sql = new StringBuilder("INSERT INTO ").append(tableName).append(" ("); StringBuilder _value_places = new StringBuilder(" VALUES("); final List<Object> values = new ArrayList<Object>(); final List<ValueAdaptor> adaptors = new ArrayList<ValueAdaptor>(); Chain head = chain.head(); while (head != null) { String colName = head.name(); MappingField mf = null; if (en != null) { mf = en.getField(colName); if (mf != null) colName = mf.getColumnNameInSql(); } sql.append(colName); if (head.special()) { _value_places.append(head.value()); } else { if (en != null) mf = en.getField(head.name()); _value_places.append("?"); values.add(head.value()); ValueAdaptor adaptor = Jdbcs.getAdaptorBy(head.value()); if (mf != null && mf.getAdaptor() != null) adaptor = mf.getAdaptor(); adaptors.add(adaptor); } head = head.next(); if (head != null) { sql.append(", "); _value_places.append(", "); } } sql.append(")"); _value_places.append(")"); sql.append(_value_places); if (log.isDebugEnabled()) log.debug(sql); dao.run(new ConnCallback() { public void invoke(Connection conn) throws Exception { PreparedStatement ps = conn.prepareStatement(sql.toString()); try { for (int i = 0; i < values.size(); i++) adaptors.get(i).set(ps, values.get(i), i + 1); ps.execute(); } finally { Daos.safeClose(ps); } } }); } /** * 为特定package下带@Table注解的类调用dao.create(XXX.class, force), * 批量建表,优先建立带@ManyMany的表 * * @param dao * Dao实例 * @param packageName * package名称,自动包含子类 * @param force * 如果表存在,是否先删后建 */ public static void createTablesInPackage(Dao dao, String packageName, boolean force) { List<Class<?>> list = new ArrayList<Class<?>>(); OUT: for (Class<?> klass : Scans.me().scanPackage(packageName)) { if (klass.getAnnotation(Table.class) != null) { Entity<?> en = dao.getEntity(klass); List<LinkField> tmp = en.getLinkFields(null); if (tmp != null && tmp.size() > 0) { for (LinkField lf : tmp) { if (lf instanceof ManyManyLinkField) { list.add(0, klass); // 优先建立带@ManyMany的表 continue OUT; } } } list.add(klass); } } for (Class<?> klass : list) { dao.create(klass, force); } } /** * 为特定package下带@Table注解的类调用dao.create(XXX.class, force), 批量建表 * * @param dao * Dao实例 * @param oneClzInPackage * 使用package中某一个class文件, 可以防止写错pkgName * @param force * 如果表存在,是否先删后建 */ public static void createTablesInPackage(Dao dao, Class<?> oneClzInPackage, boolean force) { createTablesInPackage(dao, oneClzInPackage.getPackage().getName(), force); } private static Class<?>[] iz = new Class<?>[]{Dao.class}; /** * 创建一个带FieldFilter的Dao代理实例. 注意,为避免出错,生成的Dao对象不应该传递到其他方法去. * * @param dao * 原始的Dao实例 * @param filter * 字段过滤器 * @return 带FieldFilter的Dao代理实例 */ public static Dao ext(Dao dao, FieldFilter filter) { return ext(dao, filter, null); } /** * 创建一个带TableName的Dao代理实例. 注意,为避免出错,生成的Dao对象不应该传递到其他方法去. * * @param dao * 原始的Dao实例 * @param tableName * 动态表名上下文 * @return 带TableName的Dao代理实例 */ public static Dao ext(Dao dao, Object tableName) { return ext(dao, null, tableName); } /** * 同时进行字段过滤和动态表名封装 * * @param dao * Dao实例 * @param filter * 字段过滤 * @param tableName * 动态表名参数 * @return 封装好的Dao实例 */ public static Dao ext(Dao dao, FieldFilter filter, Object tableName) { if (tableName == null && filter == null) return dao; ExtDaoInvocationHandler handler = new ExtDaoInvocationHandler(dao, filter, tableName); return (Dao) Proxy.newProxyInstance(dao.getClass().getClassLoader(), iz, handler); } @SuppressWarnings({"unchecked", "rawtypes"}) public static boolean filterFields(Object obj, FieldMatcher matcher, Dao dao, Callback2<MappingField, Object> callback) { if (obj == null) return false; obj = Lang.first(obj); if (obj == null) { return false; } if (obj.getClass() == Class.class) { throw Lang.impossible(); } if (obj instanceof String || obj instanceof Number || obj instanceof Boolean) { throw Lang.impossible(); } Entity en = dao.getEntity(obj.getClass()); if (en == null) { throw Lang.impossible(); } List<MappingField> mfs = new ArrayList<MappingField>(en.getMappingFields()); if (matcher != null) { Iterator<MappingField> it = mfs.iterator(); while (it.hasNext()) { MappingField mf = it.next(); if (!matcher.match(mf.getName())) it.remove(); } } boolean flag = false; for (MappingField mf : mfs) { if (matcher == null) { Object val = mf.getValue(obj); callback.invoke(mf, val); flag = true; continue; } if (matcher.isIgnoreId() && mf.isId()) continue; if (matcher.isIgnoreName() && mf.isName()) continue; if (matcher.isIgnorePk() && mf.isCompositePk()) continue; Object val = mf.getValue(obj); if (val == null) { if (matcher.isIgnoreNull()) continue; } else { if (matcher.isIgnoreZero() && val instanceof Number && ((Number) val).doubleValue() == 0.0) { continue; } if (matcher.isIgnoreDate() && val instanceof Date) { continue; } if (matcher.isIgnoreBlankStr() && val instanceof String) { } } callback.invoke(mf, val); flag = true; } return flag; } /** * 为数据表自动增减字段 * * @param dao * Dao实例 * @param klass * 映射Pojo * @param add * 是否允许添加字段 * @param del * 是否允许删除字段 * @param checkIndex * 是否检查索引 */ public static void migration(Dao dao, final Class<?> klass, final boolean add, final boolean del, boolean checkIndex) { migration(dao, klass, add, del, checkIndex, null); } /** * 为数据表自动增减字段 * * @param dao * Dao实例 * @param klass * 映射Pojo * @param add * 是否允许添加字段 * @param del * 是否允许删除字段 */ public static void migration(Dao dao, final Class<?> klass, final boolean add, final boolean del) { migration(dao, klass, add, del, false, null); } /** * 为数据表自动增减字段 * * @param dao * Dao实例 * @param klass * 映射Pojo * @param add * 是否允许添加字段 * @param del * 是否允许删除字段 * @param tableName * 动态表名上下文 */ public static void migration(Dao dao, final Class<?> klass, final boolean add, final boolean del, Object tableName) { migration(dao, klass, add, del, false, tableName); } /** * 为数据表自动增减字段 * * @param dao * Dao实例 * @param klass * 映射Pojo * @param add * 是否允许添加字段 * @param del * 是否允许删除字段 * @param checkIndex * 是否检查索引 * @param tableName * 动态表名上下文 */ public static void migration(Dao dao, final Class<?> klass, final boolean add, final boolean del, final boolean checkIndex, final Object tableName) { final JdbcExpert expert = dao.getJdbcExpert(); if (tableName != null && Strings.isNotBlank(tableName.toString())) { dao = ext(dao, tableName); } final Entity<?> en = dao.getEntity(klass); if (!dao.exists(klass)) return; final List<Sql> sqls = new ArrayList<Sql>(); final Set<String> _indexs = new HashSet<String>(); dao.run(new ConnCallback() { public void invoke(Connection conn) throws Exception { expert.setupEntityField(conn, en); Statement stat = null; ResultSet rs = null; ResultSetMetaData meta = null; try { // 获取数据库元信息 stat = conn.createStatement(); rs = stat.executeQuery("select * from " + en.getTableName() + " where 1 != 1"); meta = rs.getMetaData(); Set<String> columnNames = new HashSet<String>(); int columnCount = meta.getColumnCount(); for (int i = 1; i <= columnCount; i++) { columnNames.add(meta.getColumnName(i).toLowerCase()); } for (MappingField mf : en.getMappingFields()) { if (mf.isReadonly()) continue; String colName = mf.getColumnName(); if (columnNames.contains(colName.toLowerCase())) { columnNames.remove(colName.toLowerCase()); continue; } if (add) { log.infof("add column[%s] to table[%s]", mf.getColumnName(), en.getTableName()); sqls.add(expert.createAddColumnSql(en, mf)); } } if (del) { for (String colName : columnNames) { log.infof("del column[%s] from table[%s]", colName, en.getTableName()); Sql sql = Sqls.create("ALTER table $table DROP column $name"); sql.vars().set("table", en.getTableName()); sql.vars().set("name", colName); sqls.add(sql); } } // show index from mytable; if (checkIndex) _indexs.addAll(expert.getIndexNames(en, conn)); } catch (SQLException e) { if (log.isDebugEnabled()) log.debugf("migration Table '%s' fail!", en.getTableName(), e); } // Close ResultSet and Statement finally { Daos.safeClose(stat, rs); } } }); // 创建索引 UpdateIndexSql indexSqls = createIndexs(dao, en, _indexs, tableName); if (checkIndex) { // 因为已删除的字段的索引是没办法删除的 所以要先处理索引 再处理字段 Sql[] delIndexSqls = indexSqls.getSqlsDel(); if (!Lang.isEmptyArray(delIndexSqls)) { dao.execute(delIndexSqls); } } for (Sql sql : sqls) { dao.execute(sql); } if (checkIndex) { Sql[] addIndexSqls = indexSqls.getSqlsAdd(); if (!Lang.isEmptyArray(addIndexSqls)) { dao.execute(addIndexSqls); } } // 创建关联表 dao.getJdbcExpert().createRelation(dao, en); } static class UpdateIndexSql { private Sql[] sqlsAdd; private Sql[] sqlsDel; public Sql[] getSqlsAdd() { return sqlsAdd; } public void setSqlsAdd(Sql[] sqlsAdd) { this.sqlsAdd = sqlsAdd; } public Sql[] getSqlsDel() { return sqlsDel; } public void setSqlsDel(Sql[] sqlsDel) { this.sqlsDel = sqlsDel; } } private static UpdateIndexSql createIndexs(Dao dao, Entity<?> en, Set<String> indexsHis, Object t) { UpdateIndexSql uis = new UpdateIndexSql(); List<Sql> sqls = new ArrayList<Sql>(); List<String> delIndexs = new ArrayList<String>(); List<EntityIndex> indexs = en.getIndexes(); for (EntityIndex index : indexs) { sqls.add(dao.getJdbcExpert().createIndexSql(en, index)); } if (!Lang.isEmpty(sqls)) { uis.setSqlsAdd(sqls.toArray(new Sql[0])); } Iterator<String> iterator = indexsHis.iterator(); List<Sql> delSqls = new ArrayList<Sql>(); while (iterator.hasNext()) { String index = iterator.next(); if (delIndexs.contains(index) || Lang.equals("PRIMARY", index)) { continue; } MappingField mf = en.getColumn(index); if (mf != null) { if (mf.isName()) continue; } if (dao.meta().isSqlServer()) { delSqls.add(Sqls.createf("DROP INDEX %s.%s", getTableName(dao, en, t), index)); } else { delSqls.add(Sqls.createf("ALTER TABLE %s DROP INDEX %s", getTableName(dao, en, t), index)); } } if (!Lang.isEmpty(delSqls)) { uis.setSqlsDel(Lang.collection2array(delSqls)); } return uis; } /** * 为指定package及旗下package中带@Table注解的Pojo执行migration * * @param dao * Dao实例 * @param packageName * 指定的package名称 * @param add * 是否允许添加字段 * @param del * 是否允许删除字段 * @param checkIndex * 是否检查索引 * @param nameTable * 动态表名上下文 */ public static void migration(Dao dao, String packageName, boolean add, boolean del, boolean checkIndex, Object nameTable) { for (Class<?> klass : Scans.me().scanPackage(packageName)) { if (klass.getAnnotation(Table.class) != null) { migration(dao, klass, add, del, checkIndex, nameTable); } } } /** * 为指定package及旗下package中带@Table注解的Pojo执行migration * * @param dao * Dao实例 * @param packageName * 指定的package名称 * @param add * 是否允许添加字段 * @param del * 是否允许删除字段 * @param nameTable * 动态表名上下文 */ public static void migration(Dao dao, String packageName, boolean add, boolean del, Object nameTable) { migration(dao, packageName, add, del, true, nameTable); } /** * 为指定package及旗下package中带@Table注解的Pojo执行migration * * @param dao * Dao实例 * @param packageName * 指定的package名称 * @param add * 是否允许添加字段 * @param del * 是否允许删除字段 * @param checkIndex * 是否检查索引 */ public static void migration(Dao dao, String packageName, boolean add, boolean del, boolean checkIndex) { for (Class<?> klass : Scans.me().scanPackage(packageName)) { if (klass.getAnnotation(Table.class) != null) { migration(dao, klass, add, del, checkIndex, null); } } } /** * 为指定package及旗下package中带@Table注解的Pojo执行migration * * @param dao * Dao实例 * @param packageName * 指定的package名称 * @param add * 是否允许添加字段 * @param del * 是否允许删除字段 */ public static void migration(Dao dao, String packageName, boolean add, boolean del) { migration(dao, packageName, add, del, true); } /** * 检查分表中是否有字段变化 提示 * * @param dao * Dao实例 * @param tableName * 动态表名上下文 * @param clsType * 映射Pojo */ public static void checkTableColumn(Dao dao, Object tableName, final Class<?> clsType) { final NutDao d = (NutDao) dao; final JdbcExpert expert = d.getJdbcExpert(); ext(d, tableName).run(new ConnCallback() { public void invoke(Connection conn) throws Exception { Entity<?> en = d.getEntity(clsType); expert.setupEntityField(conn, en); } }); } /** * 获取动态表的表名 * * @param dao * Dao实例 * @param klass * 映射Pojo * @param target * 参考对象 */ public static String getTableName(Dao dao, Class<?> klass, Object target) { return getTableName(dao, dao.getEntity(klass), target); } /** * 获取动态表的表名 * * @param dao * Dao实例 * @param en * Pojo的数据库实体 * @param target * 参考对象 */ public static String getTableName(Dao dao, final Entity<?> en, Object target) { if (target == null) return en.getTableName(); final String[] name = new String[1]; TableName.run(target, new Runnable() { public void run() { name[0] = en.getTableName(); } }); return name[0]; } private static SqlFormat sqlFormat = SqlFormat.full; /** 获取SQL打印格式 */ public static SqlFormat getSqlFormat() { return sqlFormat; } /** * 设置SQL打印格式 * * @param sqlFormat * SQL打印格式 */ public static void setSqlFormat(SqlFormat sqlFormat) { Daos.sqlFormat = sqlFormat; } /** 获取SQL2003关键字 */ public static Set<String> sql2003Keywords() { Set<String> keywords = new HashSet<String>(); String k = "ADD,ALL,ALLOCATE,ALTER,AND,ANY,ARE,ARRAY,AS,ASENSITIVE,ASYMMETRIC,AT,ATOMIC,AUTHORIZATION,BEGIN,BETWEEN,BIGINT,BINARY,BLOB,BOOLEAN,BOTH,BY,CALL,CALLED,CASCADED,CASE,CAST,CHAR,CHARACTER,CHECK,CLOB,CLOSE,COLLATE,COLUMN,COMMIT,CONDITION,CONNECT,CONSTRAINT,CONTINUE,CORRESPONDING,CREATE,CROSS,CUBE,CURRENT,CURRENT_DATE,CURRENT_DEFAULT_TRANSFORM_GROUP,CURRENT_PATH,CURRENT_ROLE,CURRENT_TIME,CURRENT_TIMESTAMP,CURRENT_TRANSFORM_GROUP_FOR_TYPE,CURRENT_USER,CURSOR,CYCLE,DATE,DAY,DEALLOCATE,DEC,DECIMAL,DECLARE,DEFAULT,DELETE,DEREF,DESCRIBE,DETERMINISTIC,DISCONNECT,DISTINCT,DO,DOUBLE,DROP,DYNAMIC,EACH,ELEMENT,ELSE,ELSEIF,END,ESCAPE,EXCEPT,EXEC,EXECUTE,EXISTS,EXIT,EXTERNAL,FALSE,FETCH,FILTER,FLOAT,FOR,FOREIGN,FREE,FROM,FULL,FUNCTION,GET,GLOBAL,GRANT,GROUP,GROUPING,HANDLER,HAVING,HOLD,HOUR,IDENTITY,IF,IMMEDIATE,IN,INDICATOR,INNER,INOUT,INPUT,INSENSITIVE,INSERT,INT,INTEGER,INTERSECT,INTERVAL,INTO,IS,ITERATE,JOIN,LANGUAGE,LARGE,LATERAL,LEADING,LEAVE,LEFT,LIKE,LOCAL,LOCALTIME,LOCALTIMESTAMP,LOOP,MATCH,MEMBER,MERGE,METHOD,MINUTE,MODIFIES,MODULE,MONTH,MULTISET,NATIONAL,NATURAL,NCHAR,NCLOB,NEW,NO,NONE,NOT,NULL,NUMERIC,OF,OLD,ON,ONLY,OPEN,OR,ORDER,OUT,OUTER,OUTPUT,OVER,OVERLAPS,PARAMETER,PARTITION,PRECISION,PREPARE,PROCEDURE,RANGE,READS,REAL,RECURSIVE,REF,REFERENCES,REFERENCING,RELEASE,REPEAT,RESIGNAL,RESULT,RETURN,RETURNS,REVOKE,RIGHT,ROLLBACK,ROLLUP,ROW,ROWS,SAVEPOINT,SCOPE,SCROLL,SEARCH,SECOND,SELECT,SENSITIVE,SESSION_USER,SET,SIGNAL,SIMILAR,SMALLINT,SOME,SPECIFIC,SPECIFICTYPE,SQL,SQLEXCEPTION,SQLSTATE,SQLWARNING,START,STATIC,SUBMULTISET,SYMMETRIC,SYSTEM,SYSTEM_USER,TABLE,TABLESAMPLE,THEN,TIME,TIMESTAMP,TIMEZONE_HOUR,TIMEZONE_MINUTE,TO,TRAILING,TRANSLATION,TREAT,TRIGGER,TRUE,UNDO,UNION,UNIQUE,UNKNOWN,UNNEST,UNTIL,UPDATE,USER,USING,VALUE,VALUES,VARCHAR,VARYING,WHEN,WHENEVER,WHERE,WHILE,WINDOW,WITH,WITHIN,WITHOUT,YEAR"; for (String keyword : k.split(",")) { keywords.add(keyword); } keywords.remove("VALUE"); keywords.remove("SQL"); keywords.remove("YEAR"); return keywords; } /** 是否检查字段为数据库的关键字 */ public static boolean CHECK_COLUMN_NAME_KEYWORD = false; /** 是否把字段名用字符包裹来进行关键字逃逸 */ public static boolean FORCE_WRAP_COLUMN_NAME = false; /** 是否把字段名给变成大写 */ public static boolean FORCE_UPPER_COLUMN_NAME = false; public static boolean FORCE_HUMP_COLUMN_NAME = false; /** varchar 字段的默认字段长度 */ public static int DEFAULT_VARCHAR_WIDTH = 128; } class ExtDaoInvocationHandler implements InvocationHandler { protected ExtDaoInvocationHandler(Dao dao, FieldFilter filter, Object tableName) { this.dao = dao; this.filter = filter; this.tableName = tableName; } public Dao dao; public FieldFilter filter; public Object tableName; public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable { final Molecule<Object> m = new Molecule<Object>() { public void run() { try { setObj(method.invoke(dao, args)); } catch (Exception e) { throw Lang.wrapThrow(e); } } }; if (filter != null && tableName != null) { TableName.run(tableName, new Runnable() { public void run() { filter.run(m); } }); return m.getObj(); } if (filter != null) filter.run(m); else TableName.run(tableName, m); return m.getObj(); } }