Spring Boot学习笔记----mybatis注解(二)

柔情只为你懂 2022-06-04 08:14 355阅读 0赞

之前的博文讲述了mybatis注解的简单用法,包括@Select,@Insert,@Update,@Delete,@Result,@Param和@Options。本文将记录多个Provider的用法。

如何理解Provider呢?只是换了一种形式。将原来的SQL注解绑定放到了一个类里,再将该类注解绑定至原有位置。

先对比看一下形式吧。

原有SQL注解绑定

  1. @Insert("Insert into hero(name,age) values(#{sName},#{nAge})")
  2. @Options(useGeneratedKeys=true, keyColumn="id", keyProperty="id")
  3. void addHero(Hero hero);

使用provider后的形式

  1. @InsertProvider(type=HeroProvider.class,method = "addHero") void addHero(Hero hero);

即,HeroProvider类中的addHero方法所返回的SQL语句,跟@Insert所绑定的SQL语句一致。

我们注意到插入provider的绑定是使用了@InsertProvider注解。
类似的注解,闭着眼也能想到。@SelectProvider,@UpdateProvider,@DeleteProvider,对应的功能,不用闭眼也能想到。

接下来,我们看看HeroProvider的实现。

  1. package com.breakloop.mybatis.provider;
  2. import com.breakloop.mybatis.entity.Hero;
  3. import org.apache.ibatis.jdbc.SQL;
  4. import org.slf4j.Logger;
  5. import org.slf4j.LoggerFactory;
  6. public class HeroProvider {
  7. Logger logger= LoggerFactory.getLogger(HeroProvider.class);
  8. public String addHero(Hero hero){
  9. String sqlStr;
  10. SQL sql= new SQL();
  11. sql.INSERT_INTO("hero");
  12. if(hero.getAge()>0 && hero.getName()!=null){
  13. sql.VALUES("name","'"+hero.getName()+"'");
  14. sql.VALUES("age", String.valueOf(hero.getAge()));
  15. }
  16. sqlStr=sql.toString();
  17. logger.info("sql="+sqlStr);
  18. return sqlStr;
  19. }
  20. }

这里需要注意的是,SQL的VALUES方法的传参都是String类型。如果某一字段为String类型,则需要给字段数据加单引号!否则,字段数据将会被识别为字段名称,导致SQL语句异常。

再来为HeroProvider 添加选择方法。看看@SelectProvider注解的使用。

  1. public String selectByAge(int age){
  2. String sqlStr;
  3. SQL sql= new SQL();
  4. sql.SELECT("*");
  5. sql.FROM("hero");
  6. sql.WHERE("age="+age);
  7. sqlStr = sql.toString();
  8. logger.info("sql="+sqlStr);
  9. return sqlStr;
  10. }

同时,在Mapper中进行绑定。

  1. @SelectProvider(type = HeroProvider.class,method = "selectByAge") List<Hero> selectByAge(int age);

从面儿上看,没什么问题。但运行时报错。

  1. Error invoking SqlProvider method (com.breakloop.mybatis.provider.HeroProvider.selectByAge). Cannot invoke a method that holds named argument(@Param) using a specifying parameterObject. In this case, please specify a 'java.util.Map' object.]

这种情况出现在传参不是实体类或者java.util.Map时。

解决方案有两种

(1)使用@Param对参数进行绑定,即

  1. @SelectProvider(type = HeroProvider.class,method = "selectByAge") List<Hero> selectByAge(@Param("aa") int age);
  2. public String selectByAge(@Param("aa") int age){
  3. String sqlStr;
  4. SQL sql= new SQL();
  5. sql.SELECT("*");
  6. sql.FROM("hero");
  7. sql.WHERE("age=#{aa}");
  8. //或者
  9. //sql.WHERE("age="+age);
  10. sqlStr = sql.toString();
  11. logger.info("sql="+sqlStr);
  12. return sqlStr;
  13. }

(2)使用Map传参

  1. @SelectProvider(type = HeroProvider.class,method = "selectByAge") List<Hero> selectByAge(Map<String, Integer> params);
  2. public String selectByAge(Map<String,Integer> params){
  3. String sqlStr;
  4. SQL sql= new SQL();
  5. sql.SELECT("*");
  6. sql.FROM("hero");
  7. sql.WHERE("age="+params.get("age"));
  8. sqlStr = sql.toString();
  9. logger.info("sql="+sqlStr);
  10. return sqlStr;
  11. }

照葫芦画瓢,@UpdateProvider和@DeleteProvider也就没什么了。这里我们给出代码示例。

  1. @UpdateProvider(type = HeroProvider.class,method = "updateHero") void updateHero(Hero hero);
  2. @DeleteProvider(type = HeroProvider.class,method = "deleteHero") void deleteHeroByName(@Param("aa") String name,@Param("bb") int age);
  3. public String updateHero(Hero hero){
  4. String sql= new SQL(){
  5. {
  6. UPDATE("hero");
  7. if(hero.getAge()>0 && hero.getName()!=null){
  8. SET("name='"+hero.getName()+"'");
  9. SET("age="+hero.getAge());
  10. WHERE("id="+hero.getId());
  11. }
  12. }
  13. }.toString();
  14. logger.info("sql="+sql);
  15. return sql;
  16. }
  17. public String deleteHero(@Param("aa") String sName, @Param("bb") int nAge){
  18. String sql= new SQL(){
  19. {
  20. DELETE_FROM("hero");
  21. if(nAge>0){
  22. WHERE("age="+nAge);
  23. }
  24. if(sName!=null){
  25. WHERE("name='"+sName+"'");
  26. }
  27. }
  28. }.toString();
  29. logger.info("sql="+sql);
  30. return sql;
  31. }

至此,注解方式的动态SQL方法小结完毕。

感觉mybatis的水很深。很多点都要深看,短时间内只能了解如何使用。至于为什么,怎么个原理,需要再挖。当然,JPA的存在,使得选择方式变多,深挖也变犹豫。呵呵~

发表评论

表情:
评论列表 (有 0 条评论,355人围观)

还没有评论,来说两句吧...

相关阅读