Mybatis推荐用注解方式替代XML方式进行开发,这样SpringBoot+Mybatis开发就能做到“零"XML。然而Mybatis的注解方式还存在着不少的坑,比如以下SQL语句
@Select({
"<script>",
"select t.day from t",
"where ",
"t.day in " +
"<foreach item='day' collection='days' open='(' separator=',' close=')'>",
"to_char(#{day},'yyyymmdd')" +
"</foreach>",
"and t.id < 5",
"</script>"
})
List<Map<String, Object>> listLastDays(@Param("days") List<Date> days) throws Exception;
然后会报
org.apache.ibatis.builder.BuilderException: Could not find value method on SQL annotation.....
......
Caused by: org.xml.sax.SAXParseException: 元素内容必须由格式正确的字符数据或标记组成。
查Stackoverflow解释说,如果采用了<script>
标签,那么标签里面的字符串就会当成xml来处理,而小于号显然和xml文件冲突了,解决办法可以加
<![CDATA[
and t.id < 5
]]>
或者直接转义
and t.id < 5
然而这两种方法似乎不太优雅,因为需要开发人员提前预测究竟哪个字符需要进行转义。如果将<![CDATA[
直接作用于SQL语句
@Select({
"<script>",
"<![CDATA[",
"select t.day from t",
"where ",
"t.day in " +
"<foreach item='day' collection='days' open='(' separator=',' close=')'>",
"to_char(#{day},'yyyymmdd')" +
"</foreach>",
"and t.id < 5",
"]]>",
"</script>"
})
List<Map<String, Object>> listLastDays(@Param("days") List<Date> days) throws Exception;
就会报以下错误
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter 'day' not found. Available parameters are [ days, param1]
显然采用了<![CDATA[
标签,<foreach
就识别不出来了。
所以要么用之前的方法,要么就不用<script
,而采用@SqlProvider的方式进行SQL拼接,反正都没有好的解决方案。
未完待续中