1. 程式人生 > 其它 >Mybatis框架Day02之sql對映檔案(二)

Mybatis框架Day02之sql對映檔案(二)

技術標籤:Mybatis資料庫列表javamybatismysql

mapper中的名稱空間(二)

查select的引數傳遞

@Param(“id”)命名引數

命名引數,通過@Param指定引數,從而方便sql語句佔位符使用引數值#{id}
#{id,jdbcType=INT} 萬一傳入null資料,mysql插入null無問題,oracle不知道null是什麼型別

傳多個引數

攜帶兩個引數查詢時,出現異常

EmployeeDao employeeDao = sqlSession.getMapper(EmployeeDao.class);
employee = employeeDao.
getEmpByIdAndName(1, "admin");

Error querying database. Cause: org.apache.ibatis.binding.BindingException: Parameter ‘id’ not found. Available parameters are [0, 1, param1, param2]
Cause: org.apache.ibatis.binding.BindingException: Parameter ‘id’ not found. Available parameters are [0, 1, param1, param2]

形參中傳入多個引數,取值#{引數名}無效。可用0,1,param1,param2

原因:
只要傳入多個引數mybatis會自動將多個引數封裝在一個map中,使用的key是引數的索引和第幾個值
Map<String,Object> map = new HashMap<>();
map.put(“1”,傳入的值)

告訴mybatis封裝引數時使用指定的key,在定義介面方法中的形參前使用註解@Param(“id”)

傳單個引數

基本型別:取值#{隨便寫}

傳pojo

取值#{pojo的屬性名}

傳map

將多個要是用的引數封裝

拓展

method1(@Param(“id”)Integer id,#{param2}String empName,#{param3.email}Employee employee)

查select多條bean列表封裝list

List<Employee> getAllEmps();
/**
 * 查詢n條bean物件封裝list
 * @throws IOException
 */
@Test
public void testQueryAll() throws IOException {
    initSqlSessionFactory();
    SqlSession sqlSession = sqlSessionFactory.openSession();
    EmployeeDao employeeDao = sqlSession.getMapper(EmployeeDao.class);
    List<Employee> list = employeeDao.getAllEmps();
    for (Employee employee : list) {
        System.out.println(employee);
    }
}
<!--    方法返回型別集合:如果返回的是集合,寫的是集合裡面元素的型別
    List<Employee> getAllEmps();
-->
    <select id="getAllEmps" resultType="com.lwt.bean.Employee">
        select * from t_emp
    </select>

查單/多條記錄封裝map

集合裡面“元素”的型別!

單條

一條bean物件封裝map

Map<String, Object> getEmpByIdReturnMap(Integer id); // 查單條記錄,欄位名為key,值為value
/**
 * 查詢一條bean物件封裝map
 * @throws IOException
 */
@Test
public void testQueryEmpByIdReturnMap() throws IOException {
    initSqlSessionFactory();
    SqlSession sqlSession = sqlSessionFactory.openSession();
    EmployeeDao employeeDao = sqlSession.getMapper(EmployeeDao.class);
    Map<String, Object> map = employeeDao.getEmpByIdReturnMap(1);
    System.out.println(map);
}
<!--    Map<String, Object> getEmpByIdReturnMap(Integer id);-->
    <select id="getEmpByIdReturnMap" resultType="map">
        select * from t_emp where id=#{id}
    </select>

多條

org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 7

原因:

<select id="getAllEmpsReturnMap" resultType="map">

解決:
在介面方法上使用@MapKey解決此問題
MapKey:把查出結果的id作為key

理解:
resultType裡面如果是集合,必須寫集合中元素的型別(Map也是集合呀!)

程式碼:

@MapKey("id")
Map<Integer,Employee> getAllEmpsReturnMap(); // 主鍵為key,值為一條物件
@Test
public void testQueryAllEmpsReturnMap() throws IOException {
    initSqlSessionFactory();
    SqlSession sqlSession = sqlSessionFactory.openSession();
    EmployeeDao employeeDao = sqlSession.getMapper(EmployeeDao.class);
    Map<Integer, Employee> map = employeeDao.getAllEmpsReturnMap();
    System.out.println(map);
    Employee employee = map.get(1);
    System.out.println(employee);
}
<!--    Map<Integer,Object> getAllEmpsReturnMap();
    封裝map返回多條列表bean物件 *這裡不是map!?*
-->
    <select id="getAllEmpsReturnMap" resultType="com.lwt.bean.Employee">
        select * from t_emp
    </select>

#{}和${}

在sql中$和#混用
#{屬性名}:是引數預編譯方式,引數的位置用?替代,引數後來都是預編譯設定進去,安全,不會有sql注入問題
${屬性名}:不是引數預編譯,而是直接和sql語句進行拼串,不安全。

場景:動態取表明,2張日誌表 log_2021_01,log_2021_02;
查詢日誌表時,select * from log_2018_1 where id=? and empName=?
動態傳入表名,此時是${}的使用場景,不支援預編譯使用#{}

自定義結果集

手寫版

type="com.lwt.bean.Cat" 指定對哪個bean自定義封裝規則;全類名
id="myCat"唯一標識,讓人引用
<resultMap type="com.lwt.bean.Cat" id="myCat">
       id用來指定主鍵列的對應規則(javaBean屬性名)
       property指定哪個屬性封裝id這一列資料(資料庫欄位列名)
       主鍵列
    <id property="id" column="id"/>
       普通列
    <result property="name" column="cName"/>
    <result property="age" column="cAge"/>
    ...
</resultMap>
 
<select id="getCatById" resultMap="myCat">
       select * from t_cat where id=#{id}
</select>

資料庫欄位列名
在這裡插入圖片描述
bean屬性名
在這裡插入圖片描述
列名和屬性名不同時,使用自定義結果集,程式碼如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lwt.dao.CatDao">
<!--        void getCatById(Integer id);
       resultType使用預設bean規則
       使用自定義封裝規則時,刪除resultType,將resultMap定義的引用id名填在resultMap上
-->

<!--法一:起別名(bean屬性名和sql欄位名不同)        select id,cName name,cAge age,cGender gender from t_cat where id=#{id}-->
    <select id="getCatById" resultMap="myCat">
        select * from t_cat where id=#{id}
    </select>

<!--    type為哪個bean自定義封裝規則

-->
    <resultMap id="myCat" type="com.lwt.bean.Cat">
<!--        指定主鍵列的對應規則-->
        <id property="id" column="id"/>
        <result property="name" column="cName"/>
        <result property="age" column="cAge"/>
        <result property="gender" column="cGender"/>
    </resultMap>
</mapper>

測試:

/**
 * 列名和屬性名不同,需要自定義
 * @throws IOException
 */
@Test
public void queryCat() throws IOException {
    initSqlSessionFactory();
    SqlSession sqlSession = sqlSessionFactory.openSession();
    CatDao catDao = sqlSession.getMapper(CatDao.class);
    Cat cat = catDao.getCatById(1);
    System.out.println(cat);
}