jeecgboot/JeecgBoot · error · RuntimeException
解析SQL模板异常
Error message
解析SQL模板异常
What it means
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.
Source
Thrown at jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/dynamic/db/FreemarkerParseFactory.java:111
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
*
* @param tplContent 模板内容
* @param paras 参数
* @return String 模板解析后内容
*/
public static String parseTemplateContent(String tplContent,Map<String, Object> paras) {
return parseTemplateContent(tplContent, paras, false);
}
public static String parseTemplateContent(String tplContent, Map<String, Object> paras, boolean keepSpace) {
try {
String sqlUnderline="sql_";
StringWriter swriter = new StringWriter();
if (stringTemplateLoader.findTemplateSource(sqlUnderline + tplContent.hashCode()) == null) {View on GitHub (pinned to 96fb33f5ec)
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.
Example fix
# before
# userList.ftl contains ${undefinedVar}
FreemarkerParseFactory.parseTemplate("userList.ftl", paras); // -> 解析SQL模板异常
# after
# fix the template to reference only supplied params
SELECT * FROM sys_user WHERE id = :id Defensive patterns
Strategy: try-catch
Validate before calling
// sanity: template exists and params cover interpolations
if (!templateLoader.exists(tplName)) throw new IllegalArgumentException("missing tpl"); Type guard
public static boolean templateReady(String tpl, Set<String> keys){ return tpl != null && !tpl.trim().isEmpty(); } Try / catch
try { FreemarkerParseFactory.parseTemplate(tplName, paras); }
catch (RuntimeException e) { log.error("parse failed for {}: {}", tplName, e.getMessage()); throw e; } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- DaoFormat 是 minidao 保留关键字,不允许使用 ,请更改参数定义!
- 未找到对应实体
- 该编码【${parentCode}】不存在,请核实!
- 发送消息失败,消息内容为空!
- 表名不合法,存在SQL注入风险!--->{table}
AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14).
Data as JSON: /api/errors/7ff56db7d5de72ca.
Report an issue: GitHub.