最近开发中尝试使用注解来代替xml完成Mybatis的sql编写,实现更完(装)整(逼)的无xml编程。结果没写多久就跌进大坑了Orz
总所周知的是Mybatis支持的注解中有@Select、@Insert、@Update、@Delete这四个基本操作。使用这些注解你可以非常快的完成基础操作,如果想执行一些复杂操作,例如包含where、foreach等xml中一个标签即可完成的操作,便需要用到另一个注解 –> @SelectProvider
如果你的需求只是传递一些基础类型,那你学习使用SelectProvider的曲线还是很平滑的。如果你的需求是传递一些复杂类型,例如List,那就可能会尴尬了。
1 2 3 4 5 @Mapper public interface QuestionMapper { @SelectProvider(type = QuestionSqlProvider.class, method = "listQuestionByQuestionId") List<Question> listQuestionByQuestionId (@Param("idList") List<Integer> idList) ; }
一开始我理所当然的把List作为输入参数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public String listQuestionByQuestionId (final List<Integer> idList) { StringBuilder sb = new StringBuilder(); sb.append("(" ); for (Integer questionId : idList) { sb.append(" '" + questionId + "'," ); } sb.deleteCharAt(sb.length() - 1 ); sb.append(")" ); System.out.println(sb.toString()); return new SQL() {{ SELECT(" question_id,question_title,create_time " ); FROM(" question " ); WHERE(" question_id in " + sb.toString()); }}.toString(); }
燃鹅。。jvm很无情的抛了个错误出来
1 2 00:29:39.814 [http-nio-8080-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - Could not complete request org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error invoking SqlProvider method (com.amosannn.mapper.QuestionSqlProvider.listQuestionByQuestionId). Cause: org.apache.ibatis.binding.BindingException: Parameter 'arg0' not found. Available parameters are [idList, param1]
很难受,Mybatis的官方文档里并没有针对@SelectProvider有更多的demo,翻遍了各大门户网站也没见到有相关的讨论。兜兜转转依旧没有眉目,想到多参数的传递会被Mybatis自动封装进Map,该不会List也是同样被封装进Map吧。结果一试还真是这样。。
终于摸索出问题的关键,只需把形参由List类型替换为Map类型就能接收到前面传来的List了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class QuestionSqlProvider { public String listQuestionByQuestionId (final Map<String, Object> map) { List<Integer> idList = (List<Integer>)map.get("idList" ); StringBuilder sb = new StringBuilder(); sb.append("(" ); for (Integer questionId : idList) { sb.append(" '" + questionId + "'," ); } sb.deleteCharAt(sb.length() - 1 ); sb.append(")" ); System.out.println(sb.toString()); return new SQL() {{ SELECT(" question_id,question_title,create_time " ); FROM(" question " ); WHERE(" question_id in " + sb.toString()); }}.toString(); } }