You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MyBatis能否与Freemarker兼容?配置后标签失效问题咨询

问题分析与解决方案

这绝对不是Bug,而是MyBatis脚本语言机制的特性——当你把默认脚本语言设置为FreeMarker后,MyBatis会用FreeMarker的解析器来处理所有SQL语句,原来那些熟悉的MyBatis XML动态标签(<if>、<choose>这类)会被FreeMarker当成普通文本直接输出,根本不会被解析执行,这就是为什么你的SQL里会同时出现TOP和LIMIT的原因。

之前没配置FreeMarker时,MyBatis用的是默认的XML脚本语言解析器,能正确识别并执行<if>、<choose>的逻辑,所以功能正常。

下面给你几个可行的解决方案:

方案1:彻底切换到FreeMarker语法重写动态SQL

既然已经把默认脚本语言设为FreeMarker,不如直接用FreeMarker的指令来替代原来的MyBatis标签。针对你的例子,改写后的SQL应该是这样的:

<select id="find" parameterType="map" resultType="com.example.MyType">
  SELECT 
  <#if _databaseId == 'sqlserver'>
    TOP (${rowLimit}) 
  </#if>
  FROM myexampletable 
  <#choose>
    <#when _databaseId == 'oracle'>
      WHERE rownum <= ${rowLimit}
    </#when>
    <#when _databaseId == 'postgresql' || _databaseId == 'h2'>
      LIMIT ${rowLimit}
    </#when>
  </#choose>
</select>

这里要注意,FreeMarker里直接用${rowLimit}引用参数就行,不需要原来的${r"#{rowLimit}"}写法,MyBatis的FreeMarker驱动会自动帮你处理参数绑定,不用担心SQL注入问题。

方案2:按需使用FreeMarker,保留默认XML脚本

如果你不想全部切换,只想在特定语句里用FreeMarker,可以去掉全局的defaultScriptingLanguage设置,只保留typeAlias,然后在需要用FreeMarker的SQL标签上通过lang属性指定:

<!-- 全局配置调整 -->
<settings>
  <!-- 移除defaultScriptingLanguage的设置 -->
</settings>
<typeAliases>
  <typeAlias type="org.mybatis.scripting.freemarker.FreeMarkerLanguageDriver" alias="FreeMarker"/>
</typeAliases>

<!-- 需要用FreeMarker的语句加上lang属性 -->
<select id="findWithFreemarker" parameterType="map" resultType="com.example.MyType" lang="FreeMarker">
  <!-- 这里写FreeMarker语法的SQL -->
</select>

<!-- 其他语句继续用原来正常的MyBatis XML动态SQL -->
<select id="find" parameterType="map" resultType="com.example.MyType">
  SELECT <if test="_databaseId == 'sqlserver'"> TOP (${r"#{rowLimit}"}) </if>
  FROM myexampletable 
  <choose>
    <when test="_databaseId == 'oracle'"> WHERE rownum &lt;= ${r"#{rowLimit}"} </when>
    <when test="_databaseId == 'postgresql' || _databaseId == 'h2'"> LIMIT ${r"#{rowLimit}"} </when>
  </choose>
</select>

关于“同时混用两种语言”的说明

很遗憾,MyBatis的每个SQL语句只能由一种脚本语言解析器处理,没办法在同一个<select>标签里同时让MyBatis XML标签和FreeMarker指令都生效——解析器是排他的,要么用XML脚本解析,要么用FreeMarker解析,二者不可兼得。所以你只能二选一,或者把不同逻辑拆分到不同的SQL语句中。

内容的提问来源于stack exchange,提问作者Petr Sládek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:18:44