jeecgboot/JeecgBoot · error · RuntimeException

DaoFormat 是 minidao 保留关键字,不允许使用 ,请更改参数定义!

Error message

DaoFormat 是 minidao 保留关键字,不允许使用 ,请更改参数定义!

What it means

Thrown by FreemarkerParseFactory.parseTemplate when the caller's parameter map already contains the key 'DaoFormat' (MINI_DAO_FORMAT constant). The method needs to inject its own SimpleFormat helper under that exact key, so a collision is treated as a programming error. It is wrapped/rethrown as a generic '解析SQL模板异常' RuntimeException.

Source

Thrown at jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/dynamic/db/FreemarkerParseFactory.java:99

            return false;
        }
        return true;
    }

    /**
     * 解析ftl模板
     *
     * @param tplName 模板名
     * @param paras   参数
     * @return
     */
    public static String parseTemplate(String tplName, Map<String, Object> paras) {
        try {
            log.debug(" minidao sql templdate : " + tplName);
            StringWriter swriter = new StringWriter();
            Template mytpl = TPL_CONFIG.getTemplate(tplName, ENCODE);
            if (paras.containsKey(MINI_DAO_FORMAT)) {
                throw new RuntimeException("DaoFormat 是 minidao 保留关键字,不允许使用 ,请更改参数定义!");
            }
            paras.put(MINI_DAO_FORMAT, new SimpleFormat());
            mytpl.process(paras, swriter);
            String sql = getSqlText(swriter.toString());
            paras.remove(MINI_DAO_FORMAT);
            return sql;
        } catch (Exception e) {
            log.error(e.getMessage(), e.fillInStackTrace());
            log.error("发送一次的模板key:{ " + tplName + " }");
            //System.err.println(e.getMessage());
            //System.err.println("模板名:{ "+ tplName +" }");
            throw new RuntimeException("解析SQL模板异常");
        }
    }

    /**
     * 解析ftl
     *

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. Rename the conflicting business parameter to something other than 'DaoFormat'.
  2. Build a fresh HashMap for each minidao call instead of reusing/mutating a shared map.
  3. Strip the reserved key defensively before calling parseTemplate: paras.remove("DaoFormat").
  4. Document the reserved key in your DAO layer so future params avoid it.

Example fix

// before
Map<String,Object> paras = new HashMap<>();
paras.put("DaoFormat", "report"); // reserved!
FreemarkerParseFactory.parseTemplate("userList.ftl", paras);

// after
paras.put("format", "report");
FreemarkerParseFactory.parseTemplate("userList.ftl", paras);
Defensive patterns

Strategy: validation

Validate before calling

if (paras.containsKey("DaoFormat")) paras.remove("DaoFormat");
FreemarkerParseFactory.parseTemplate(tplName, paras);

Type guard

public static boolean noReservedKeys(Map<String,Object> p){ return p == null || !p.containsKey("DaoFormat"); }

Try / catch

try { FreemarkerParseFactory.parseTemplate(t, p); }
catch (RuntimeException e) { log.error("template {} failed: {}", t, e.getMessage()); }

Prevention

When it happens

Trigger: A minidao DAO method receives a parameter Map that was built with a key literally named 'DaoFormat', or a copy/merge of two maps accidentally carried the reserved key over. Common in custom minidao SQL templates and report SQL templating.

Common situations: Developer named a real business field 'daoFormat'/'DaoFormat'; a generic map-merge utility duplicated keys across parameter sources; a template param builder reused a static map without clearing.

Related errors


AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14). Data as JSON: /api/errors/e7c8a136fb539412. Report an issue: GitHub.