{"record":{"id":"7ff56db7d5de72ca","repo":"jeecgboot/JeecgBoot","slug":"sql-7ff56d","errorCode":null,"errorMessage":"解析SQL模板异常","messagePattern":"解析SQL模板异常","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/dynamic/db/FreemarkerParseFactory.java","lineNumber":111,"sourceCode":"    public static String parseTemplate(String tplName, Map<String, Object> paras) {\n        try {\n            log.debug(\" minidao sql templdate : \" + tplName);\n            StringWriter swriter = new StringWriter();\n            Template mytpl = TPL_CONFIG.getTemplate(tplName, ENCODE);\n            if (paras.containsKey(MINI_DAO_FORMAT)) {\n                throw new RuntimeException(\"DaoFormat 是 minidao 保留关键字，不允许使用 ，请更改参数定义！\");\n            }\n            paras.put(MINI_DAO_FORMAT, new SimpleFormat());\n            mytpl.process(paras, swriter);\n            String sql = getSqlText(swriter.toString());\n            paras.remove(MINI_DAO_FORMAT);\n            return sql;\n        } catch (Exception e) {\n            log.error(e.getMessage(), e.fillInStackTrace());\n            log.error(\"发送一次的模板key:{ \" + tplName + \" }\");\n            //System.err.println(e.getMessage());\n            //System.err.println(\"模板名:{ \"+ tplName +\" }\");\n            throw new RuntimeException(\"解析SQL模板异常\");\n        }\n    }\n\n    /**\n     * 解析ftl\n     *\n     * @param tplContent 模板内容\n     * @param paras      参数\n     * @return String 模板解析后内容\n     */\n    public static String parseTemplateContent(String tplContent,Map<String, Object> paras) {\n        return parseTemplateContent(tplContent, paras, false);\n    }\n    public static String parseTemplateContent(String tplContent, Map<String, Object> paras, boolean keepSpace) {\n        try {\n            String sqlUnderline=\"sql_\";\n            StringWriter swriter = new StringWriter();\n            if (stringTemplateLoader.findTemplateSource(sqlUnderline + tplContent.hashCode()) == null) {","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/dynamic/db/FreemarkerParseFactory.java#L93-L129","documentation":"Thrown by FreemarkerParseFactory.parseTemplate's catch-all when ANY exception occurs during FreeMarker template processing — template not found, syntax error in the .ftl, an undefined variable reference, the reserved-key collision (error 49), or an I/O error. The original message is logged but only the generic '解析SQL模板异常' is surfaced to the caller, which makes root-causing require the log.","triggerScenarios":"An .ftl template referenced by tplName does not exist in the template loader; a ${var} in the template has no matching key in paras; invalid FreeMarker syntax; a map key collision (DaoFormat); or the template string itself is malformed SQL after rendering.","commonSituations":"Renaming a DAO method without renaming its .ftl file; changing a parameter name but not the template; deploying a partial jar missing template resources; Freemarker version change introducing stricter parsing.","solutions":["Read the preceding log.error lines — they print the real exception message and the offending template name.","Confirm the .ftl file exists at the expected path and is packaged in the jar/war resources.","Align every ${param} in the template with keys actually supplied in the paras map.","If caused by error 49, fix the reserved key first."],"exampleFix":"# before\n# userList.ftl contains ${undefinedVar}\nFreemarkerParseFactory.parseTemplate(\"userList.ftl\", paras); // -> 解析SQL模板异常\n\n# after\n# fix the template to reference only supplied params\nSELECT * FROM sys_user WHERE id = :id","handlingStrategy":"try-catch","validationCode":"// sanity: template exists and params cover interpolations\nif (!templateLoader.exists(tplName)) throw new IllegalArgumentException(\"missing tpl\");","typeGuard":"public static boolean templateReady(String tpl, Set<String> keys){ return tpl != null && !tpl.trim().isEmpty(); }","tryCatchPattern":"try { FreemarkerParseFactory.parseTemplate(tplName, paras); }\ncatch (RuntimeException e) { log.error(\"parse failed for {}: {}\", tplName, e.getMessage()); throw e; }","preventionTips":["Log the underlying exception — the surfaced message is generic.","Unit-test templates with representative param maps.","Keep template names and param names in lockstep across refactors."],"tags":["freemarker","minidao","template","runtime","jeecg-boot"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}