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

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

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

先对比看一下形式吧。

原有SQL注解绑定

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

使用provider后的形式

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

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

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

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

package com.breakloop.mybatis.provider;

import com.breakloop.mybatis.entity.Hero;
import org.apache.ibatis.jdbc.SQL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HeroProvider {
    Logger logger= LoggerFactory.getLogger(HeroProvider.class);

    public String addHero(Hero hero){
        String sqlStr;
        SQL sql= new SQL();
        sql.INSERT_INTO("hero");

        if(hero.getAge()>0 && hero.getName()!=null){
            sql.VALUES("name","'"+hero.getName()+"'");
            sql.VALUES("age", String.valueOf(hero.getAge()));
        }
        sqlStr=sql.toString();
        logger.info("sql="+sqlStr);
        return sqlStr;
    }
}

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

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

    public String selectByAge(int age){
        String sqlStr;
        SQL sql= new SQL();
        sql.SELECT("*");
        sql.FROM("hero");
        sql.WHERE("age="+age);
        sqlStr = sql.toString();
        logger.info("sql="+sqlStr);
        return sqlStr;
    }

同时,在Mapper中进行绑定。

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

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

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对参数进行绑定,即

    @SelectProvider(type = HeroProvider.class,method = "selectByAge")
    List<Hero> selectByAge(@Param("aa") int age);
    public String selectByAge(@Param("aa") int age){
        String sqlStr;
        SQL sql= new SQL();
        sql.SELECT("*");
        sql.FROM("hero");
        sql.WHERE("age=#{aa}");
        //或者
        //sql.WHERE("age="+age);
        sqlStr = sql.toString();
        logger.info("sql="+sqlStr);
        return sqlStr;
    }

(2)使用Map传参

    @SelectProvider(type = HeroProvider.class,method = "selectByAge")
    List<Hero> selectByAge(Map<String, Integer> params);
    public String selectByAge(Map<String,Integer> params){
        String sqlStr;
        SQL sql= new SQL();
        sql.SELECT("*");
        sql.FROM("hero");
        sql.WHERE("age="+params.get("age"));
        sqlStr = sql.toString();
        logger.info("sql="+sqlStr);
        return sqlStr;
    }

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

    @UpdateProvider(type = HeroProvider.class,method = "updateHero")
    void updateHero(Hero hero);

    @DeleteProvider(type = HeroProvider.class,method = "deleteHero")
    void deleteHeroByName(@Param("aa") String name,@Param("bb") int age);
    public String updateHero(Hero hero){
        String sql= new SQL(){
            {
                UPDATE("hero");
                if(hero.getAge()>0 && hero.getName()!=null){
                    SET("name='"+hero.getName()+"'");
                    SET("age="+hero.getAge());
                    WHERE("id="+hero.getId());
                }
            }
        }.toString();
        logger.info("sql="+sql);
        return sql;
    }

    public String deleteHero(@Param("aa") String sName, @Param("bb") int nAge){
        String sql= new SQL(){
            {
                DELETE_FROM("hero");
                if(nAge>0){
                    WHERE("age="+nAge);
                }
                if(sName!=null){
                    WHERE("name='"+sName+"'");
                }
            }
        }.toString();
        logger.info("sql="+sql);
        return sql;
    }

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

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值