JFinal实践笔记——Model保存时生成seq.nextval和sysdate

Model或Record能方便自动生成SQL,将set的值作为SQL参数,只针对主键采用序列的情况进行了单独处理,对于非主键字段采用序列、使用函数等情况只能另外采用手写SQL来处理,这对Model和Record来说算是不小的遗憾。

我的设想是对set过来的序列、函数等值进行下封装,在生成SQL时进行检查,如果满足条件就直接生成到SQL中,不作为参数。重新定义一个OracleDialect如下

/**
 * 字段值允许不作为参数,生成到Sql中,可以设置序列、数据库函数,甚至子查询 
 * record.set("seqno","#(to_char(sysdate,'yymmddhh24miss')||lpad(seq.nextval,8,'0'))");
 * record.set("createdate","#(sysdate)");<br>
 * record.set("photo","#(empty_blob())");
 */
public class _OracleDialect extends OracleDialect {
    private static final String INSQL_PREFIX = "#(";
    private static final String INSQL_SUFFIX = ")";
    
    // 对原有seq.nextval的处理保持兼容
    protected boolean isInSql(String value) {
        return value.startsWith(INSQL_PREFIX) && value.endsWith(INSQL_SUFFIX)
                || value.endsWith(".nextval");
    }
    
    protected String getInSqlValue(String value) {
        return value.endsWith(".nextval")? value: value.substring(INSQL_PREFIX.length(), value.length()-1);
    }
    
    // insert into table (id,name) values(seq.nextval, ?)
    @Override
    public void forModelSave(Table table, Map<String, Object> attrs, StringBuilder sql, List<Object> paras) {
        sql.append("insert into ").append(table.getName()).append('(');
        StringBuilder temp = new StringBuilder(") values(");
//        String[] pKeys = table.getPrimaryKey();
        int count = 0;
        for (Entry<String, Object> e: attrs.entrySet()) {
            String colName = e.getKey();
            if (table.hasColumnLabel(colName)) {
                if (count++ > 0) {
                    sql.append(", ");
                    temp.append(", ");
                }
                sql.append(colName);
                Object value = e.getValue();
//                if (value instanceof String && isPrimaryKey(colName, pKeys) && ((String)value).endsWith(".nextval")) {
                    //temp.append(value);
                if (value instanceof String && isInSql((String)value)) {
                    temp.append(getInSqlValue((String)value));
                } else {
                    temp.append('?');
                    paras.add(value);
                }
            }
        }
        sql.append(temp.toString()).append(')');
    }
    
    @Override
    public void forDbSave(String tableName, String[] pKeys, Record record, StringBuilder sql, List<Object> paras) {
        tableName = tableName.trim();
        trimPrimaryKeys(pKeys);
        
        sql.append("insert into ");
        sql.append(tableName).append('(');
        StringBuilder temp = new StringBuilder();
        temp.append(") values(");
        
        int count = 0;
        for (Entry<String, Object> e: record.getColumns().entrySet()) {
            String colName = e.getKey();
            if (count++ > 0) {
                sql.append(", ");
                temp.append(", ");
            }
            sql.append(colName);
            
            Object value = e.getValue();
//            if (value instanceof String && isPrimaryKey(colName, pKeys) && ((String)value).endsWith(".nextval")) {
//                temp.append(value);
            if (value instanceof String && isInSql((String)value)) {
                temp.append(getInSqlValue((String)value));
            } else {
                temp.append('?');
                paras.add(value);
            }
        }
        sql.append(temp.toString()).append(')');
    }
}

ActiveRecordPlugin插件初始化的相关代码

ActiveRecordPlugin arp = new ActiveRecordPlugin(dp);
// 配置Oracle方言
arp.setDialect(new _OracleDialect());
// 配置属性名(字段名)大小写不敏感容器工厂
arp.setContainerFactory(new CaseInsensitiveContainerFactory());

还可以改进,比如在Model和Record类里提供封装方法

public Record setInSql(String column, String value) {
        getColumns().put(column, "#("+value+")");
        return this;
 }


评论区

JFinal

2017-08-24 11:51

这个需求一直没有人反馈过,头一次看到,感谢你的分享

热门分享

扫码入社