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);
}