最近使用JBolt極速開發平臺在做一個項目,使用的是Sqlserver數據庫,表註釋和字段註釋都做好了,在Mysql下生成一點問題沒有,在Sqlserver下生成卻發現列註釋remarks獲取不到,無法正確生成!
debug發現是JDBC-Sqlserver的坑,沒有很好的去實現標準,獲取remarks無效。
無奈只能靠Sql語句自行查詢解決了。
這裏給出了自定義擴展SqlServer的MetaBuilder去解決了這個問題。
主要是buildTabelColumnRemark實現通過sql查詢每個表的字段註釋。
具體代碼:
package cn.jbolt.common.gen;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.List;
import javax.sql.DataSource;
import com.jfinal.kit.Kv;
import com.jfinal.plugin.activerecord.dialect.SqlServerDialect;
import com.jfinal.plugin.activerecord.generator.ColumnMeta;
import com.jfinal.plugin.activerecord.generator.TableMeta;
public class _JBoltSqlServerMetaBuilder extends JBoltMetaBuilder {
private Connection columnRemarkConn;
public _JBoltSqlServerMetaBuilder(DataSource dataSource) {
super(dataSource);
}
@Override
protected void buildColumnMetas(TableMeta tableMeta) throws SQLException {
String sql = dialect.forTableBuilderDoBuild(tableMeta.name);
Statement stm = conn.createStatement();
ResultSet rs = stm.executeQuery(sql);
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
Kv remarkKv = null;
if (generateRemarks) {
remarkKv = buildTabelColumnRemark(tableMeta.name);
}
ColumnMeta cm;
for (int i = 1; i <= columnCount; i++) {
cm = new ColumnMeta();
cm.name = rsmd.getColumnName(i);
String colClassName = rsmd.getColumnClassName(i);
String typeStr = typeMapping.getType(colClassName);
if (typeStr != null) {
cm.javaType = typeStr;
} else {
int type = rsmd.getColumnType(i);
if (type == Types.BINARY || type == Types.VARBINARY || type == Types.BLOB) {
cm.javaType = "byte[]";
} else if (type == Types.SMALLINT) {
cm.javaType = "java.lang.Short";
} else if (type == Types.CLOB || type == Types.NCLOB) {
cm.javaType = "java.lang.String";
} else {
cm.javaType = "java.lang.String";
}
}
// 特殊處理char(1) to Boolean
if ("java.lang.String".equals(cm.javaType)) {
int scale = rsmd.getScale(i); // 小數點右邊的位數,值爲 0 表示整數
int precision = rsmd.getPrecision(i); // 最大精度
if (scale == 0 && precision == 1 && JBoltProjectGenConfig.charToBoolean) {
cm.javaType = "java.lang.Boolean";
}
}
// 構造字段對應的屬性名 attrName
cm.attrName = buildAttrName(cm.name);
// 備註字段賦值
if (generateRemarks) {
cm.remarks = remarkKv.getStr(cm.name);
}
tableMeta.columnMetas.add(cm);
}
rs.close();
stm.close();
}
@Override
protected ResultSet getTablesResultSet() throws SQLException {
setDialect(new SqlServerDialect());
ResultSet rs = dbMeta.getTables(conn.getCatalog(), null, "%", new String[] { "TABLE" });
return rs;
}
@Override
protected void buildTableNames(List<TableMeta> ret) throws SQLException {
ResultSet rs = getTablesResultSet();
while (rs.next()) {
String schem = rs.getString("TABLE_SCHEM");
String tableName = rs.getString("TABLE_Name");
if (schem.equals("sys")) {
JBoltConsoleUtil.printMessage(" Skip table :" + tableName + ",sys table");
continue;
}
if (excludedTables.contains(tableName)) {
JBoltConsoleUtil.printMessage(" Skip table :" + tableName);
continue;
}
if (isSkipTable(tableName)) {
JBoltConsoleUtil.printMessage(" Skip table :" + tableName);
continue;
}
TableMeta tableMeta = new TableMeta();
tableMeta.name = tableName;
if (generateRemarks) {
tableMeta.remarks = getTabelRemark(tableName);
}
tableMeta.modelName = buildModelName(tableName);
tableMeta.baseModelName = buildBaseModelName(tableMeta.modelName);
ret.add(tableMeta);
}
rs.close();
if (generateRemarks && columnRemarkConn != null && columnRemarkConn.isClosed() == false) {
columnRemarkConn.close();
}
}
protected String getTabelRemark(String table) throws SQLException {
Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery("SELECT cast(ds.value as varchar(200)) as remarks "
+ " FROM sys.extended_properties ds" + " LEFT JOIN sysobjects tbs ON ds.major_id=tbs.id"
+ " WHERE ds.minor_id=0 and tbs.name='" + table + "'");
String remark = null;
if (rs.next()) {
remark = rs.getString("remarks");
}
rs.close();
return remark;
}
private Kv buildTabelColumnRemark(String table) throws SQLException {
if (columnRemarkConn == null) {
columnRemarkConn = dataSource.getConnection();
}
Statement statement = columnRemarkConn.createStatement();
ResultSet rs = statement.executeQuery("SELECT cast(col.name as varchar(200)) AS name ,"
+ " cast(ISNULL(ep.[value], '') as varchar(200)) AS remarks" + " FROM dbo.syscolumns col"
+ " LEFT JOIN dbo.systypes t ON col.xtype = t.xusertype"
+ " inner JOIN dbo.sysobjects obj ON col.id = obj.id" + " AND obj.xtype = 'U'" + " AND obj.status >= 0"
+ " LEFT JOIN dbo.syscomments comm ON col.cdefault = comm.id"
+ " LEFT JOIN sys.extended_properties ep ON col.id = ep.major_id" + " AND col.colid = ep.minor_id"
+ " AND ep.name = 'MS_Description'"
+ " LEFT JOIN sys.extended_properties epTwo ON obj.id = epTwo.major_id" + " AND epTwo.minor_id = 0"
+ " AND epTwo.name = 'MS_Description'" + " WHERE obj.name = '" + table + "'");
Kv kv = Kv.create();
while (rs.next()) {
kv.set(rs.getString("name"), rs.getString("remarks"));
}
rs.close();
return kv;
}
}
這樣再去執行代碼生成就沒有任何問題了!
表註釋和字段註釋都沒問題了!
方案用的是笨辦法,目前快速搞定,先用上,誰有更好的方法,可以交流。
諮詢加入,加我微信:
mumengmeng