Mybatis進(jìn)階

1.數(shù)據(jù)庫(kù)的環(huán)境切換

2.注解方式

?## 推薦使用xml

a.將sql語(yǔ)句寫(xiě)在接口的方法前面
b.將接口的全類名寫(xiě)入到<mapper>,讓mybatis知道sql語(yǔ)句此時(shí)是存儲(chǔ)在接口中的。

注意:注解和XML都支持批量引入

 <mappers>
         <!--以下可以將com.itt.mapper包中的注解接口和xml            
       全部一次性引入-->
        <package name="com.itt.mapper"/>
 </mappers>

3.增刪改的返回問(wèn)題

  • 返回值 可以是void ,Integer,Long,Boolean,只需要在接口中改返回值就可以了!

4.事務(wù)提交方式

  • 手動(dòng)提交:
SqlSession session = sessionFactory.openSession();
session.commit();//執(zhí)行完commit時(shí),手動(dòng)提交 事務(wù)
  • 自動(dòng)提交 :每一個(gè)dml語(yǔ)句自動(dòng)提交
SqlSession session = sessionFactory.openSession(true);

5.參數(shù)問(wèn)題

  • 目前將多個(gè)參數(shù)封裝到一個(gè)javabean對(duì)象(pojo),然后使用該對(duì)象傳遞

  • a.傳入多個(gè)參數(shù)時(shí),不用在mapper.xml中編寫(xiě)parameterType

    異常提示:

  • stuNo不能使用,使用的是:【arg3,arg2,arg1,arg0,param3,param2,param1】

    <insert id="insertEmpInfo">
            insert into empinfo(id,name,age,job,phone)
            values (#{arg0},#{arg1},#{arg2},#{arg3},#{arg4})
        </insert>
    
  • b. 命名參數(shù)的方式

    可以在接口中通過(guò)@Param("")來(lái)指定sql中參數(shù)的名字

    void insertEmpInfo(@Param("sId") String id,
                           @Param("sName")  String name,
                           @Param("sAge") String age,
                           @Param("sJob") String job,
                           @Param("sPhone") String phone);
    
    <insert id="insertEmpInfo">
            insert into empinfo(id,name,age,job,phone)
            values (#{sId},#{sName},#{sAge},#{sJob},#{sPhone})
        </insert>
    
  • c. 綜合使用的情況

    //一個(gè)是簡(jiǎn)單類型 ,一個(gè)是對(duì)象類型
    void insertEmpInfo(@Param("sId") String id,@Param("empInfo")  EmpInfo empInfo);
    
    <insert id="insertEmpInfo">
        insert into empinfo(id,name,age,job,phone)
        values (#{sId},#{empInfo.name},#{empInfo.age},#{empInfo.job},#{empInfo.phone})
    </insert>
    

6.增加null

  • oracle:如果插入的 字段是null,提示錯(cuò)誤:Other 而不是gnull

  • mysql:如果插入的字段是null,可以正常執(zhí)行(沒(méi)有約束)

  • 原因:

  • 各個(gè)數(shù)據(jù)庫(kù)在Mybatis中對(duì)各種數(shù)據(jù)類型的默認(rèn)值不一致。

?mybatis中,jdbcTypeForNull(如果是null),則默認(rèn)值OTHER。

在mysql中,mybatis將Other當(dāng)做NULL來(lái)處理了,但是oracle不行。

解決:

? oracle:null -> OTHER 手工告訴oracle:other -> null

a. 當(dāng)某個(gè)數(shù)據(jù)類型oracle無(wú)法處理進(jìn),告訴它用默認(rèn)值null 來(lái)處理

//使用#{empInfo.name,jdbcType=null}這個(gè)就可以了
<insert id="insertEmpInfo">
    insert into empinfo(id,name,age,job,phone)
    values (#{sId},#{empInfo.name,jdbcType=null},#{empInfo.age},#{empInfo.job},#{empInfo.phone})
</insert>

b. 配置mybatis全局配置文件conf.xml

<settings>
    <setting name="jdbcTypeForNull" value="NUll"/>
</settings>

7.返回值為HashMap的情況

  • 注意:在mysql中@MapKey("id")字段為小寫(xiě)
  • 在oracle中為全大寫(xiě)
  • map:
    • key:id value:Student
  • 程序根據(jù)select的返回值,知道m(xù)ap的value就是EmpInfo,根據(jù)@MapKey("id")知道Map的key是id
@MapKey("id")
HashMap<String,EmpInfo> queryAllEmp();
<select id="queryAllEmp" resultType="HashMap">
    select * from empinfo
</select>

8.ResultMap:字段和屬性名的相應(yīng)

  • column指的是數(shù)據(jù)庫(kù)中的列名
  • property指的是類中的名字
<select id="queryAllEmpins" resultType="HashMap"
            resultMap="EmpInoMap">
        select * from empinfo
    </select>
    <resultMap id="EmpInoMap" type="empInfo">
        <id column="eid" property="id"/>
        <result column="ename" property="name"/>
        <result column="eage" property="age"/>
        <result column="ejob" property="job"/>
        <result column="ephone" property="phone"/>
    </resultMap>

9.別名問(wèn)題

<!--設(shè)置單個(gè)/多個(gè)別名-->
    <typeAliases>
        <!--單個(gè)別名(別名 忽略大小寫(xiě))-->
        <!--<typeAlias type="com.itt.entity.Student" alias="student"/>-->
        <!--批量定義別名,以下會(huì)自動(dòng)將該包中的所有類 批量定義別名:別名就是類名(不帶包名的類名)-->
        <package name="com.itt.entity"/>
    </typeAliases>
  • 當(dāng)這個(gè)包下的子包 與Student重名時(shí),必須使用注解的方式重新命名
@Alias("myempinfo")
public class EmpInfo {
    
}

10.處理where子句后面的and的三種方式

  • trim標(biāo)簽可以去掉后面的 and
  • <trim>可以處理拼接sql中【開(kāi)頭或結(jié)尾】第一個(gè)and
<select id="queryByINP" parameterType="EmpInfo" resultType="EmpInfo">
  select * from empinfo where
    <trim>
      <if test="id != null and id != 0">
          id = #{id} and 
      </if>
      <if test="name != null and name != ''">
          name like '%${name}%' and
      </if>
      <if test="phone != null and phone != ''">
          phone = #{phone} and 
      </if>
    </trim>
</select>
  • prefix="where":在整個(gè)語(yǔ)句中加where
  • prefix="set":在整個(gè)語(yǔ)句中加set,可用于更新
  • prefixOverrides="and":智能處理前面的and
  • suffixOverrides="and":智能處理后面的and
  • suffixOverrides=",":智能處理后面的,常用于更新
<trim prefix="where" prefixOverrides="and">
          <if test="id != null and id != 0">
              and id = #{id}
          </if>
          <if test="name != null and name != ''">
              and name like '%${name}%'
          </if>
          <if test="phone != null and phone != ''">
              and phone = #{phone}
          </if>
 </trim>
  • <where>標(biāo)簽可以去掉前面的and
<select id="queryByINP" parameterType="EmpInfo" resultType="EmpInfo">
  select * from empinfo
  <where>
      <if test="id != null and id != 0">
          and id = #{id}
      </if>
      <if test="name != null and name != ''">
          and name like '%${name}%'
      </if>
      <if test="phone != null and phone != ''">
          and phone = #{phone}
      </if>
  </where>
</select>
  • 直接 在where后面加:1 = 1
<select id="queryByINP" parameterType="EmpInfo" resultType="EmpInfo">
  select * from empinfo where 1 = 1
      <if test="id != null and id != 0">
          and id = #{id}
      </if>
      <if test="name != null and name != ''">
          and name like '%${name}%'
      </if>
      <if test="phone != null and phone != ''">
          and phone = #{phone}
      </if>
</select>

11.內(nèi)置參數(shù)

  • _paramter:代表Mybatis的輸入?yún)?shù)
<select id="queryByINP" parameterType="EmpInfo" resultType="EmpInfo">
  select * from empinfo
    <trim prefix="where" prefixOverrides="and">
      <if test="id != null and id != 0">
          and id = #{id}
      </if>
      <if test="name != null and name != ''">
          and ename like '%${name}%'
      </if>
      //_parameter替代parameterType這個(gè)輸入的對(duì)象
      <if test="_parameter.phone != null and _parameter.phone != ''">
          and phone = #{_parameter.phone}
      </if>
    </trim>
</select>
  • _databaseId:代表當(dāng)前數(shù)據(jù)庫(kù)的名字

12.模糊查詢?nèi)N方式

12.1

  • ${}原樣輸出
stuName like '%${stuName}%'
  • {}自動(dòng)拼接' ':可以防止SQL注入

12.2 傳值時(shí),直接 傳 %x%

student.setStuName("%s%");
stuName like #{stuName}

12.3 bind參數(shù)

<bind name="_queryName" value="'%'+name+'%'"/>
    <if test="name != null and name != ''">
         and name like #{_queryName}
    </if>
I:\MyBatisIdea\MyBatisGenerator\src\main\java

13.逆向工程

1.導(dǎo)入依賴

2.xml模板文件(修改生成路徑、表名)

3.根據(jù)java模板類一鍵生成

  • 根據(jù)學(xué)生表->學(xué)生類、學(xué)生Mapper接口、studentMapper.xml

4.如何使用

? * 增加Mybatis配置文件 conf.xml

  • 對(duì)于like模糊查詢,逆向工程需要在傳值時(shí) 寫(xiě)入%x%

逆向工程的實(shí)例:使用的是StudentExample

  • 測(cè)試類
@Test
    public  void queryAllEmpById() throws Exception{
        //Connection - SqlSession操作myBatis

        //config.xml  -> reader
        Reader reader = Resources.getResourceAsReader("conf.xml");

        //reader  ->SqlSession
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession session = sessionFactory.openSession();

        StudentMapper mapper = session.getMapper(StudentMapper.class);

        StudentExample example = new StudentExample();
        StudentExample.Criteria criteria = example.createCriteria();
        criteria.andStunameLike("%d%");



        StudentExample example1 = new StudentExample();
        StudentExample.Criteria criteria1 = example1.createCriteria();
        //模糊查詢
        criteria1.andStunoEqualTo(10);
        criteria1.andStunameLike("%k%");

        //使用exampl整合的方式實(shí)現(xiàn)or操作
        example.or(criteria1);
        //Example中的Criteria:為查詢的條件
        List<Student> students = mapper.selectByExample(example);

        System.out.println(students);


        session.close();
    }

14.MyBatis架構(gòu)和源碼解析

  • Mybatis源碼的幾個(gè)主要部件

MyBatis中步驟:

  • 1.獲取SqlSessionFactory對(duì)象
  • 2.獲取SqlSession對(duì)象
  • 3.獲取xxxMapper對(duì)象(代理接口 中的方法、mapper.xml中的<select>標(biāo)簽)
  • 4.執(zhí)行標(biāo)簽中定義的SQL語(yǔ)句

1.獲取SqlSessionFactory對(duì)象

  • parse解析器
    • 通過(guò)Configuration標(biāo)簽設(shè)置了properties、typeAliases、environments等
  • Mybatis將所有的配置信息存放到了Configuration configuration對(duì)象中
    • mapperElement的過(guò)程
  • <select id="",resultType="",parameterType="">等屬性是通過(guò)
    parseStatementNode()這個(gè)方法解析的


  • Mybatis會(huì)將xxxMapper.xml文件解析成MappedStatement對(duì)象
  • 即parseStatementNode對(duì)象就是xxxMapper文件中的標(biāo)簽

  • MapperStatement -》存在于Configuration中

  • environment -》存在于Configuration中

  • 所有的配置信息、增刪改標(biāo)簽全部存在于Configuration中

    結(jié)論:
    SqlSessionFactory對(duì)象—》DefaultSqlSessionFactory—》Configuration—》所有的配置信息

2.獲取SqlSession對(duì)象(Executor為執(zhí)行器)

  • configuration.newExecutor(tx, execType);-》默認(rèn)類型為simpleExecutor
  • 并且根據(jù)不同的類型execType,產(chǎn)生不同的Executor,并對(duì)執(zhí)行器進(jìn)行攔截操作:
executor = (Executor) interceptorChain.pluginAll(executor);
  • 作用:以后如果我們要給MyBatis寫(xiě)自己的插件,就可以通過(guò)攔截器實(shí)現(xiàn):

  • 下圖就是使用攔截器一次次增強(qiáng)執(zhí)行器Executor,從而使Executor有更強(qiáng)大的功能!

  • 返回的是:
    DefaultSqlSession(configuration, executor, 事務(wù)問(wèn)題);

  • SqlSession ->openSession()--->openSessionFromDataSource() -->DefaultSqlSession對(duì)象

  • 執(zhí)行的流程
  • SqlSession -> DefaultSqlSession對(duì)象 -> 執(zhí)行SQL

  • 插件開(kāi)發(fā):
    1.寫(xiě)插件
    2.把插件放入到攔截器中

  • 插件

select * from student --》攔截器

目標(biāo)對(duì)象target的包裝后的產(chǎn)物 --->metaObject.getValue("可以從target中獲取")

通過(guò)打印語(yǔ)句,可知,target就是 RoutingStatementHandler

----------》

metaObject.getValue("可以從RoutingStatementHandler中獲取")

可以從RoutingStatementHandler獲得:getBoundSql,getParameterHandler

------->--->metaObject.getValue("parameterHandler")

  • metaObject.getValue("parameterHandler.parameterObject")//xxxMapper.xml中的語(yǔ)句中的參數(shù)值
  • metaObject.getValue("parameterHandler.boundSql")//xxxMapper.xml中sql的語(yǔ)句

3.獲取xxxMapper對(duì)象(代理接口 中的方法、mapper.xml中的<select>標(biāo)簽)

4.執(zhí)行標(biāo)簽中定義的SQL語(yǔ)句

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. 簡(jiǎn)介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射的優(yōu)秀的...
    笨鳥(niǎo)慢飛閱讀 6,224評(píng)論 0 4
  • 前言 接著上一篇Mybatis入門(mén)繼續(xù),上一篇主要演示了Mybatis的基本操作,對(duì)數(shù)據(jù)庫(kù)的增刪改查,但是在實(shí)際項(xiàng)...
    AI賀賀閱讀 1,677評(píng)論 0 2
  • 對(duì)象之間的關(guān)系: 關(guān)聯(lián)關(guān)系:A對(duì)象依賴B對(duì)象,并且把B對(duì)象作為A對(duì)象的一個(gè)屬性,則A和B是依賴關(guān)系. ** 按照多...
    CoderZS閱讀 694評(píng)論 0 8
  • 前言 MyBatis是一個(gè)優(yōu)秀的持久層ORM框架,它對(duì)jdbc的操作數(shù)據(jù)庫(kù)的過(guò)程進(jìn)行封裝,使開(kāi)發(fā)者只需要關(guān)注SQL...
    AI喬治閱讀 662評(píng)論 0 5
  • 今天終于可以去上班了,還有一堆事兒等著處理,于是早早來(lái)到了學(xué)校。 看到張雪老師分身乏力于是就幫他就幫他...
    海博喬森教育孫老師閱讀 58評(píng)論 0 0

友情鏈接更多精彩內(nèi)容