1. 程式人生 > >Spring Boot學習筆記----mybatis註解(二)

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的存在,使得選擇方式變多,深挖也變猶豫。呵呵~