public void addComment(Dao dao, Entity<?> en, String commentTable, String commentColumn) { if (!en.hasTableComment() && !en.hasColumnComment()) { return; } List<Sql> sqls = new ArrayList<Sql>(); // 表注释 if (en.hasTableComment()) { Sql tableCommentSQL = Sqls.create(Strings.isBlank(commentTable) ? DEFAULT_COMMENT_TABLE : commentTable); tableCommentSQL .vars() .set("table", en.getTableName()) .set("tableComment", en.getTableComment()); sqls.add(tableCommentSQL); } // 字段注释 if (en.hasColumnComment()) { for (MappingField mf : en.getMappingFields()) { if (mf.hasColumnComment()) { Sql columnCommentSQL = Sqls.create(Strings.isBlank(commentColumn) ? DEFAULT_COMMENT_COLUMN : commentColumn); columnCommentSQL .vars() .set("table", en.getTableName()) .set("column", mf.getColumnName()) .set("columnComment", mf.getColumnComment()); sqls.add(columnCommentSQL); } } } // 执行创建语句 dao.execute(sqls.toArray(new Sql[sqls.size()])); }
protected List<Sql> createIndexs(Entity<?> en) { List<Sql> sqls = new ArrayList<Sql>(); StringBuilder sb = new StringBuilder(); List<EntityIndex> indexs = en.getIndexes(); for (EntityIndex index : indexs) { sb.setLength(0); if (index.isUnique()) sb.append("Create UNIQUE Index "); else sb.append("Create Index "); if (index.getName().contains("$")) sb.append(TableName.render(new CharSegment(index.getName()))); else sb.append(index.getName()); sb.append(" ON ").append(en.getTableName()).append("("); for (EntityField field : index.getFields()) { if (field instanceof MappingField) { MappingField mf = (MappingField) field; sb.append(mf.getColumnNameInSql()).append(','); } else { throw Lang.makeThrow( DaoException.class, "%s %s is NOT a mapping field, can't use as index field!!", en.getClass(), field.getName()); } } sb.setCharAt(sb.length() - 1, ')'); sqls.add(Sqls.create(sb.toString())); } return sqls; }
public String evalFieldType(MappingField mf) { if (mf.getCustomDbType() != null) return mf.getCustomDbType(); switch (mf.getColumnType()) { case INT: // 用户自定义了宽度 if (mf.getWidth() > 0) return "NUMERIC(" + mf.getWidth() + ")"; // 用数据库的默认宽度 return "INT"; case FLOAT: // 用户自定义了精度 if (mf.getWidth() > 0 && mf.getPrecision() > 0) { return "NUMERIC(" + mf.getWidth() + "," + mf.getPrecision() + ")"; } // 用默认精度 if (mf.getTypeMirror().isDouble()) return "NUMERIC(15,10)"; return "NUMERIC"; case BINARY: return "BYTEA"; case DATETIME: return "TIMESTAMP"; default: break; } return super.evalFieldType(mf); }
public ValueAdaptor getAdaptor(MappingField ef) { Mirror<?> mirror = ef.getTypeMirror(); // 为数字型枚举的特殊判断 if (mirror.isEnum() && ColType.INT == ef.getColumnType()) return Jdbcs.Adaptor.asEnumInt; // 用普通逻辑返回适配器 return Jdbcs.getAdaptor(mirror); }
@Test public void test_override_field() { Entity<?> en = en(Pet2.class); MappingField ef = en.getField("nickName"); assertEquals("alias", ef.getColumnName()); assertEquals(1, en.cloneBeforeInsertMacroes().size()); }
public String makePksName(Entity<?> en) { String name = en.getType().getAnnotation(PK.class).name(); if (Strings.isBlank(name)) { StringBuilder sb = new StringBuilder(); for (MappingField mf : en.getPks()) { sb.append("_").append(mf.getColumnName()); } sb.setLength(sb.length() - 1); return sb.toString(); } return name; }
/** * 执行一个特殊的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.getColumnName(); } 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); } } }); }
public Chain updateBy(Entity<?> entity) { if (null != entity) { Entry current = head; while (current != null) { MappingField ef = entity.getField(current.name); if (null != ef) { current.name = ef.getColumnName(); } current = current.next; } } return head(); }
@Override protected String evalFieldType(MappingField mf) { if (mf.getCustomDbType() != null) return mf.getCustomDbType(); switch (mf.getColumnType()) { case BOOLEAN: return "SMALLINT"; case INT: // 用户自定义了宽度 // if (mf.getWidth() > 0) // return "decimal(" + mf.getWidth() + ")"; // 用数据库的默认宽度 return "INTEGER"; case FLOAT: // 用户自定义了精度 if (mf.getWidth() > 0 && mf.getPrecision() > 0) { return "decimal(" + mf.getWidth() + "," + mf.getPrecision() + ")"; } // 用默认精度 if (mf.getTypeMirror().isDouble()) return "decimal(15,10)"; return "FLOAT"; default: break; } return super.evalFieldType(mf); }
// TODO not tested!! public boolean createEntity(Dao dao, Entity<?> en) { StringBuilder sb = new StringBuilder("CREATE TABLE " + en.getTableName() + "("); // 创建字段 for (MappingField mf : en.getMappingFields()) { sb.append('\n').append(mf.getColumnName()); sb.append(' ').append(evalFieldType(mf)); // 非主键的 @Name,应该加入唯一性约束 if (mf.isName() && en.getPkType() != PkType.NAME) { sb.append(" UNIQUE NOT NULL"); } // 普通字段 else { if (mf.isNotNull() || mf.isPk()) sb.append(" NOT NULL"); if (mf.hasDefaultValue()) sb.append(" DEFAULT '").append(getDefaultValue(mf)).append('\''); if (mf.isAutoIncreasement()) sb.append(" generated by default as identity "); if (mf.isPk() && en.getPks().size() == 1) { sb.append(" primary key "); } } sb.append(','); } // 结束表字段设置 sb.setCharAt(sb.length() - 1, ')'); // 执行创建语句 dao.execute(Sqls.create(sb.toString())); // 创建联合主键 if (en.getPks().size() > 1) { sb = new StringBuilder(); sb.append("ALTER TABLE ").append(en.getTableName()).append(" ADD CONSTRAINT PK_"); sb.append(makePksName(en)); sb.append(" PRIMARY KEY ("); for (MappingField mf : en.getPks()) { sb.append(mf.getColumnName()).append(","); } sb.setCharAt(sb.length() - 1, ')'); dao.execute(Sqls.create(sb.toString())); } // 创建关联表 createRelation(dao, en); // 创建索引 dao.execute(createIndexs(en).toArray(new Sql[0])); // 添加注释(表注释与字段注释) addComment(dao, en); return true; }
@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 = 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.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; } if (val instanceof Number && ((Number) val).doubleValue() == 0.0) { if (matcher.isIgnoreZero()) continue; } if (val instanceof Date) { if (matcher.isIgnoreDate()) continue; } callback.invoke(mf, val); flag = true; } return flag; }
public void setupEntityField(Connection conn, Entity<?> en) { Statement stat = null; ResultSet rs = null; ResultSetMetaData rsmd = null; try { // 获取数据库元信息 stat = conn.createStatement(); rs = stat.executeQuery(createResultSetMetaSql(en)); rsmd = rs.getMetaData(); // 循环字段检查 for (MappingField mf : en.getMappingFields()) { try { int ci = Daos.getColumnIndex(rsmd, mf.getColumnName()); // 是否只读,如果人家已经是指明是只读了,那么就不要自作聪明得再从数据库里验证了 // if (!mf.isReadonly() && rsmd.isReadOnly(ci)) // mf.setAsReadonly(); // 是否非空 if (ResultSetMetaData.columnNoNulls == rsmd.isNullable(ci)) mf.setAsNotNull(); // 枚举类型在数据库中的值 if (mf.getTypeMirror().isEnum()) { if (Daos.isIntLikeColumn(rsmd, ci)) { mf.setColumnType(ColType.INT); } else { mf.setColumnType(ColType.VARCHAR); } } } catch (Exception e) { // TODO 需要log一下不? } } } catch (Exception e) { if (log.isDebugEnabled()) log.debugf("Table '%s' doesn't exist!", en.getViewName()); } // Close ResultSet and Statement finally { Daos.safeClose(stat, rs); } }
protected String getDefaultValue(MappingField mf) { return mf.getDefaultValue(null).replaceAll("@", "@@"); }
public boolean createEntity(Dao dao, Entity<?> en) { StringBuilder sb = new StringBuilder("CREATE TABLE " + en.getTableName() + "("); // 创建字段 for (MappingField mf : en.getMappingFields()) { if (mf.isReadonly()) continue; sb.append('\n').append(mf.getColumnName()); // 自增主键特殊形式关键字 if (mf.isId() && mf.isAutoIncreasement()) { sb.append(" SERIAL"); } else { sb.append(' ').append(evalFieldType(mf)); // 非主键的 @Name,应该加入唯一性约束 if (mf.isName() && en.getPkType() != PkType.NAME) { sb.append(" UNIQUE NOT NULL"); } // 普通字段 else { if (mf.isUnsigned()) sb.append(" UNSIGNED"); if (mf.isNotNull()) sb.append(" NOT NULL"); if (mf.isAutoIncreasement()) throw Lang.noImplement(); if (mf.hasDefaultValue()) sb.append(" DEFAULT '").append(getDefaultValue(mf)).append('\''); } } sb.append(','); } // 创建主键 List<MappingField> pks = en.getPks(); if (!pks.isEmpty()) { sb.append('\n'); sb.append( String.format( "CONSTRAINT %s_pkey PRIMARY KEY (", en.getTableName().replace('.', '_').replace('"', '_'))); for (MappingField pk : pks) { sb.append(pk.getColumnName()).append(','); } sb.setCharAt(sb.length() - 1, ')'); sb.append("\n "); } // 结束表字段设置 sb.setCharAt(sb.length() - 1, ')'); // 执行创建语句 dao.execute(Sqls.create(sb.toString())); // 创建索引 dao.execute(createIndexs(en).toArray(new Sql[0])); // 创建关联表 createRelation(dao, en); // 添加注释(表注释与字段注释) addComment(dao, en); return true; }
@Override public ValueAdaptor getAdaptor(MappingField ef) { if (ef.getTypeMirror().isOf(Blob.class)) return new BlobValueAdaptor2(Jdbcs.getFilePool()); return super.getAdaptor(ef); }
/** * 执行一个特殊的Chain(事实上普通Chain也能执行,但不建议使用) * * @see org.nutz.dao.Chain#addSpecial(String, Object) */ @SuppressWarnings({"rawtypes"}) public static int updateBySpecialChain( Dao dao, Entity en, String tableName, Chain chain, Condition cnd) { if (en != null) tableName = en.getTableName(); if (tableName == null) throw Lang.makeThrow(DaoException.class, "tableName and en is NULL !!"); final StringBuilder sql = new StringBuilder("UPDATE ").append(tableName).append(" SET "); Chain head = chain.head(); final List<Object> values = new ArrayList<Object>(); final List<ValueAdaptor> adaptors = new ArrayList<ValueAdaptor>(); while (head != null) { MappingField mf = null; if (en != null) mf = en.getField(head.name()); String colName = head.name(); if (mf != null) colName = mf.getColumnName(); sql.append(colName).append("="); if (head.special()) { if (head.value() != null && head.value() instanceof String) { String str = (String) head.value(); if (str.length() > 0) { switch (str.charAt(0)) { case '+': case '-': case '*': case '/': case '%': case '&': case '^': case '|': sql.append(colName); break; } } } sql.append(head.value()); } else { sql.append("?"); values.add(head.value()); ValueAdaptor adaptor = Jdbcs.getAdaptorBy(head.value()); if (mf != null && mf.getAdaptor() != null) adaptor = mf.getAdaptor(); adaptors.add(adaptor); } sql.append(" "); head = head.next(); if (head != null) sql.append(", "); } if (cnd != null) sql.append(" ").append(cnd.toSql(en)); if (log.isDebugEnabled()) log.debug(sql); final int[] ints = new int[1]; 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); ints[0] = ps.executeUpdate(); } finally { Daos.safeClose(ps); } } }); return ints[0]; }
public void addDefaultValue(StringBuilder sb, MappingField mf) { if (!mf.hasDefaultValue()) return; if (mf.getTypeMirror().isNumber()) sb.append(" DEFAULT ").append(getDefaultValue(mf)); else sb.append(" DEFAULT '").append(getDefaultValue(mf)).append('\''); }
public ValueAdaptor getAdaptor(MappingField ef) { if (ef.getTypeMirror().isBoolean()) return new DB2BooleanAdaptor(); return super.getAdaptor(ef); }
/** 根据Pojo生成数据字典,zdoc格式 */ public static StringBuilder dataDict(DataSource ds, 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 = Jdbcs.getExpert(ds); NutDao dao = new NutDao(ds); Method evalFieldType; try { evalFieldType = exp.getClass().getDeclaredMethod("evalFieldType", MappingField.class); } catch (Throwable e) { throw Lang.wrapThrow(e); } evalFieldType.setAccessible(true); 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; try { dataType = (String) evalFieldType.invoke(exp, field); } catch (Throwable e) { throw Lang.wrapThrow(e); // 不可能发生的 } 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; }
public String evalFieldType(MappingField mf) { if (mf.getCustomDbType() != null) return mf.getCustomDbType(); switch (mf.getColumnType()) { case CHAR: return "CHAR(" + mf.getWidth() + ")"; case BOOLEAN: return "BOOLEAN"; case VARCHAR: return "VARCHAR(" + mf.getWidth() + ")"; case TEXT: return "TEXT"; case BINARY: return "BLOB"; case TIMESTAMP: return "TIMESTAMP"; case DATETIME: return "DATETIME"; case DATE: return "DATE"; case TIME: return "TIME"; case INT: // 用户自定义了宽度 if (mf.getWidth() > 0) return "INT(" + mf.getWidth() + ")"; // 用数据库的默认宽度 return "INT"; case FLOAT: // 用户自定义了精度 if (mf.getWidth() > 0 && mf.getPrecision() > 0) { return "NUMERIC(" + mf.getWidth() + "," + mf.getPrecision() + ")"; } // 用默认精度 if (mf.getTypeMirror().isDouble()) return "NUMERIC(15,10)"; return "FLOAT"; case PSQL_ARRAY: return "ARRAY"; case PSQL_JSON: case MYSQL_JSON: return "JSON"; // TODO 这里不用加 default 么 } throw Lang.makeThrow( "Unsupport colType '%s' of field '%s' in '%s' ", mf.getColumnType(), mf.getName(), mf.getEntity().getType().getName()); }