9. Mybatis 小技巧

捞月亮的小北發表於2024-06-23

1. #{ } 和 $

#{ } 和 ${ } 的區別

#{ }:先編譯sql語句,再給佔位符傳值,底層是PreparedStatement實現。可以防止sql注入,比較常用。

${}:先進行sql語句拼接,然後再編譯sql語句,底層是Statement實現。存在sql注入現象。只有在需要進行sql語句關鍵字拼接的情況下才會用到。

什麼情況下必須使用${}

當需要進行sql語句關鍵字拼接的時候。必須使用${}

  • 拼接表名:程式碼演示:

    <select id="selectAllByTableName" resultType="car">
      select
      id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carType
      from
      ${tableName}
    </select>
    
  • 批次刪除 , 程式碼演示:

    <delete id="deleteBatch">
      delete from t_car where id in(${ids})
    </delete>
    
  • 模糊查詢

    • 使用${} 程式碼演示:

      <select id="selectLikeByBrand" resultType="Car">
        select
        id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carType
        from
        t_car
        where
        brand like '%${brand}%'
      </select>
      
    • 使用#{}程式碼演示:

      • 第一種:concat函式

        <select id="selectLikeByBrand" resultType="Car">
          select
          id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carType
          from
          t_car
          where
          brand like concat('%',#{brand},'%')
        </select>
        
      • 第二種:雙引號方式 : 這種方法比較常用

        <select id="selectLikeByBrand" resultType="Car">
          select
          id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carType
          from
          t_car
          where
          brand like "%"#{brand}"%"
        </select>
        

2. typeAliases

2.1 第一種方式:typeAlias

程式碼演示:

    <typeAliases>
        <typeAlias type="com.north.mybatis.pojo.Car"></typeAlias>
    </typeAliases>
  • 首先要注意typeAliases標籤的放置位置,如果不清楚的話,可以看看錯誤提示資訊。

    image

  • typeAliases標籤中的typeAlias可以寫多個。

  • typeAlias:

    • type屬性:指定給哪個類起別名
    • alias屬性:別名。
  • alias屬性不是必須的,如果預設的話,type屬性指定的型別名的簡類名作為別名。

  • alias是大小寫不敏感的。也就是說假設alias="Car",再用的時候,可以CAR,也可以car,也可以Car,都行。

2.2 第二種方式:package (比較常用)

程式碼演示:

    <typeAliases>
        <package name="com.north.mybatis.pojo"/>
    </typeAliases>

如果一個包下的類太多,每個類都要起別名,會導致typeAlias標籤配置較多,所以mybatis用提供package的配置方式,只需要指定包名,該包下的所有類都自動起別名,別名就是簡類名。並且別名不區分大小寫。

3. mappers 設定講解

SQL對映檔案的配置方式包括四種:

  • resource:從類路徑中載入
  • url:從指定的全限定資源路徑中載入
  • class:使用對映器介面實現類的完全限定類名
  • package:將包內的對映器介面實現全部註冊為對映器

3.1 resource 講解

這種方式是從類路徑中載入配置檔案,所以這種方式要求SQL對映檔案必須放在resources目錄下或其子目錄下。

<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>

3.2 URL 講解

這種方式顯然使用了絕對路徑的方式,這種配置對SQL對映檔案存放的位置沒有要求,隨意。

<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>

3.3 class 講解 (記住這種包命名方式)

如果使用這種方式必須滿足以下條件:

  • SQL對映檔案和mapper介面放在同一個目錄下。
  • SQL對映檔案的名字也必須和mapper介面名一致。
<!-- 使用對映器介面實現類的完全限定類名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>

將CarMapper.xml檔案移動到和mapper介面同一個目錄下:

  • 在resources目錄下新建:com/powernode/mybatis/mapper【這裡千萬要注意:不能這樣新建 com.powernode.mybatis.dao】
  • 將CarMapper.xml檔案移動到mapper目錄下
  • 修改mybatis-config.xml檔案
<mappers>
  <mapper class="com.powernode.mybatis.mapper.CarMapper"/>
</mappers>

3.4 package

如果class較多,可以使用這種package的方式,但前提條件和上一種方式一樣。

<!-- 將包內的對映器介面實現全部註冊為對映器 -->
<mappers>
  <package name="com.north.mybatis.mapper"/>
</mappers>

4. idea配置檔案模板

mybatis-config.xml和SqlMapper.xml檔案可以在IDEA中提前建立好模板,以後透過模板建立配置檔案。

image

5. 插入資料時獲取自動生成的主鍵

前提是:主鍵是自動生成的。

業務背景:一個使用者有多個角色。

插入一條新的記錄之後,自動生成了主鍵,而這個主鍵需要在其他表中使用時。

插入一個使用者資料的同時需要給該使用者分配角色:需要將生成的使用者的id插入到角色表的user_id欄位上。

第一種方式:可以先插入使用者資料,再寫一條查詢語句獲取id,然後再插入user_id欄位。【比較麻煩】

第二種方式:mybatis提供了一種方式更加便捷。

image

CarMapper 程式碼

/**
     * 獲取自動生成的主鍵
     * @param car
     */
void insertUseGeneratedKeys(Car car);

CarMapper.xml 程式碼

<insert id="insertUseGeneratedKeys" useGeneratedKeys="true" keyProperty="id">
  insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
</insert>

測試程式碼:

@Test
public void testInsertUseGeneratedKeys(){
    CarMapper mapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
    Car car = new Car();
    car.setCarNum("5262");
    car.setBrand("BYD漢");
    car.setGuidePrice(30.3);
    car.setProduceTime("2020-10-11");
    car.setCarType("新能源");
    mapper.insertUseGeneratedKeys(car);
    SqlSessionUtil.openSession().commit();
    System.out.println(car.getId());
}