1、insert 標簽
1.1 獲取SqlSessionFactory 物件的通用方法
方便后面分測驗;
//獲取SqlSessionFactory 物件的通用方法
public SqlSessionFactory getSqlSessionFactory() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
return new SqlSessionFactoryBuilder().build(inputStream);
}
1.2 屬性說明
| 屬性名 | 說明 |
|---|---|
| id | namespace指定介面中的方法名 |
| parameterType | 指定介面方法入參型別,可寫可不寫(mybatis可用根據介面方法,自動推斷型別) |
| useGeneratedKey | insert標簽的屬性,告訴mybatis,執行插入操作,需要回傳自增的主鍵 |
| keyColumn | 自增主鍵的 欄位名(可以不寫,一張表只用能有一個自增主鍵) |
| keyPropert | 指定回傳的自增主鍵值,交給入參物體的哪個屬性保存 |
注意:增刪改操作,和select查詢標簽最大的區別是:回傳只有影響行數,所有沒有resultType屬性,而查詢必須有resultType;
1.3 SQL
<!-- int insertAnime(Anime animeForm); -->
<insert id="insertAnime" useGeneratedKeys="true" keyColumn="id" keyProperty="id" >
insert into `animes`(
`cid`,
`name`
)values(
#{cid},
#{name}
)
</insert>
1.4 測驗
注意:mybatis 默認對增刪改操作,事務是不自動提交(自動提交是關閉的);
需要開啟自動提交,或這是手動提交;
| 開啟自動提交 | openSession(true); |
|---|---|
| 手動提交 | sqlSession.commit(); |
@Test
public void testMybatisMapperC() throws IOException {
//獲取SqlSession物件
// SqlSession sqlSession = getSqlSessionFactory().openSession();
//方式2:創建SqlSession物件時,指定事務自動提交-true,默認false
SqlSession sqlSession = getSqlSessionFactory().openSession(true);
//獲取mapper介面的代理實作物件
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
System.out.println(animeMapper); //org.apache.ibatis.binding.MapperProxy@224edc67
//模擬從前端獲取引數,封裝請求物體
Anime animeForm = new Anime();
animeForm.setCid(1);
animeForm.setName("蠟筆小新");
//執行添加動漫
int row = animeMapper.insertAnime(animeForm);
//mybatis 默認對增刪改操作,事務是不自動提交(自動提交是關閉的)
//方式1:手動提交
//sqlSession.commit();
System.out.println(String.format("----------執行添加動漫,影響行數:%d--------", row));
//獲取自增主鍵
System.out.println(String.format("----------執行添加動漫,新增的自增id:%d--------", animeForm.getId()));
}
2、update 標簽
2.1 SQL
<!-- int updateAnimeById(Anime animeForm); -->
<update id="updateAnimeById">
update `animes` set
`cid` = #{cid},
`name` = #{name}
where `id` = #{id}
</update>
2.2 測驗
@Test
public void testMybatisMapperU() throws IOException {
SqlSession sqlSession = getSqlSessionFactory().openSession(true);
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
//模擬從前端獲取引數,封裝請求物體
Anime animeForm = new Anime();
animeForm.setId(648);
animeForm.setCid(1);
animeForm.setName("蠟筆小新5");
//執行修改動漫
int row = animeMapper.updateAnimeById(animeForm);
System.out.println(String.format("----------執行修改動漫,影響行數:%d--------", row));
}
3、delete 標簽
3.1 SQL
<!-- int deleteAnimeById(Integer animeId); -->
<delete id="deleteAnimeById">
delete from `animes`
where `id` = #{animeId}
</delete>
3.2 測驗
@Test
public void testMybatisMapperD() throws IOException {
SqlSession sqlSession = getSqlSessionFactory().openSession(true);
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
//模擬從前端獲取引數,封裝請求物體
Anime animeForm = new Anime();
animeForm.setId(648);
//執行洗掉動漫
int row = animeMapper.deleteAnimeById(animeForm.getId());
System.out.println(String.format("----------執行洗掉動漫,影響行數:%d--------", row));
}
4、select 標簽
4.1 屬性說明
| 屬性名 | 說明 |
|---|---|
| id | 對應就是namespace指定介面中的查詢方法名 |
| parameterType | 指定介面方法入參型別,可寫可不寫(建議不寫) |
| resultType | 指定介面回傳的目標型別(建議使用全類名,也可以使用別名) |
- #{id}:這就告訴 MyBatis 創建一個預處理陳述句(PreparedStatement)引數,在 JDBC 中,這樣的一個引數在 SQL 中會由一個“?”來標識,并被傳遞到一個新的預處理陳述句中;
- 如果介面只有一個引數,引數名,可以隨便寫,建議跟形參名保持一致;
4.2 一個引數
4.2.1 SQL
介面只有一個引數,引數名,可以隨便寫,建議跟形參名保持一致;
<!-- Anime selectAnimeById(Integer animeId); -->
<select id="selectAnimeById" resultType="com.kgc.mybatis.bean.Anime">
select `id`,
`cid`,
`name`
from `animes`
where `id` = #{animeId}
</select>
4.2.2 測驗
@Test
public void testMybatisMapperSelectParams1() throws IOException{
SqlSession sqlSession = getSqlSessionFactory().openSession();
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
//呼叫mapper介面,根據動漫編號查詢動漫資訊
Anime anime = animeMapper.selectAnimeById(101);
System.out.println(String.format("1.一個引數 根據動漫編號:%d,查詢動漫詳情%s",anime.getId(),anime));
}
4.3 兩個引數
多個引數,沒有自定義引數別名時可以使用
- 形參名
- 內置引數 0,1,...
- 內置引數 param1,param2,...
自定義引數別名@Param("自定義引數名")時可以使用:
- 自定義引數名
- 內置引數 param1,param2,...
4.3.1 SQL
4.3.1.1 沒有自定義引數別名:
Anime selectAnimeByNameAndCid(String animeName,Integer animeId);
<!-- Anime selectAnimeByNameAndCid(String animeName,Integer animeId); -->
<select id="selectAnimeByNameAndCid" resultType="com.kgc.mybatis.bean.Anime">
select `id`,
`cid`,
`name`
from `animes`
where `name` = #{animeName}
and `cid` = #{animeId}
<!--
where `name` = #{0}
and `cid` = #{1}
-->
<!--
where `name` = #{ param1}
and `cid` = #{param2}
-->
</select>
4.3.1.2 自定義引數別名:
Anime selectAnimeByNameAndCid(@Param("animeName") String animeName,@Param("animeId") Integer animeId);
Anime selectAnimeByNameAndCid(@Param("animeName") String animeName,@Param("animeId") Integer animeId);
<select id="selectAnimeByNameAndCid" resultType="com.kgc.mybatis.bean.Anime">
select `id`,
`cid`,
`name`
from `animes`
where `name` = #{animeName}
and `cid` = #{animeId}
<!--
where `name` = #{ param1}
and `cid` = #{param2}
-->
</select>
自定義了引數名,如果使用#{0},#{1}會報錯
Cause: org.apache.ibatis.binding.BindingException: Parameter '0' not found. Available parameters are [animeId, animeName, param1, param2]
4.3.2 測驗
@Test
public void testMybatisMapperSelectParams2() throws IOException{
SqlSession sqlSession = getSqlSessionFactory().openSession();
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
//通過動漫名稱和分類編號查詢動漫資訊
Anime anime = animeMapper.selectAnimeByNameAndCid("完美世界",3);
System.out.println(String.format("2.兩個引數 根據動漫編號:%d,查詢動漫詳情%s",anime.getId(),anime));
}
4.4 物體引數
不自定義引數別名:
- 必須 只寫 屬性名 cid author
自定義引數別名:
- 使用 別名.屬性名
- 使用 param1.屬性名
4.4.1 SQL
4.4.1.1 不自定義引數別名
Anime selectAnimeByAnime(Anime animeForm);
<select id="selectAnimeByAnime" resultType="com.kgc.mybatis.bean.Anime">
select `id`,
`cid`,
`name`
from `animes`
where `cid` = #{cid}
and `author` = #{author}
</select>
4.4.1.2 自定義引數別名
Anime selectAnimeByAnime(@Param("animeForm") Anime animeForm);
<select id="selectAnimeByAnime" resultType="com.kgc.mybatis.bean.Anime">
select `id`,
`cid`,
`name`
from `animes`
<!--
where `cid` = #{animeForm.cid}
and `author` = #{animeForm.author}
-->
where `cid` = #{param1.cid}
and `author` = #{param1.author}
</select>
4.4.2 測驗
@Test
public void testMybatisMapperSelectParams3() throws IOException{
SqlSession sqlSession = getSqlSessionFactory().openSession();
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
//通過動漫分類編號和作者查詢動漫資訊
Anime animeForm = new Anime();
animeForm.setCid(1);
animeForm.setAuthor("三少");
Anime anime = animeMapper.selectAnimeByAnime(animeForm);
System.out.println(String.format("3.物體引數 根據動漫編號:%d,查詢動漫詳情%s",anime.getId(),anime));
}
4.5 Map集合引數
- 通過Map 的 **鍵值 **獲取引數
4.5.1 SQL
<!--
Anime selectAnimeByActorAndCid(Map<String,Object> queryMap);
-->
<select id="selectAnimeByActorAndCid" resultType="com.kgc.mybatis.bean.Anime">
select `id`,
`cid`,
`name`
from `animes`
where `cid` = #{cid}
and `actor` = #{actor}
</select>
4.5.2 測驗
@Test
public void testMybatisMapperSelectParams4() throws IOException{
SqlSession sqlSession = getSqlSessionFactory().openSession();
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
//通過動漫分類編號和主角查詢動漫資訊
Map<String,Object> queryMap = new HashMap<>();
queryMap.put("cid","2");
queryMap.put("actor","路飛");
Anime anime = animeMapper.selectAnimeByActorAndCid(queryMap);
System.out.println(String.format("4.集合引數 根據動漫編號:%d,查詢動漫詳情%s",anime.getId(),anime));
}
4.6 #{} 和 ${} 的區別
#{}:
-
類似于PreparedStatement
-
可以獲取普通引數,自定義引數,物體引數,集合引數等;
-
底層使用的是?占位符,會進行預編譯處理,可以防止SQL注入問題,安全性高;
-
不可以進行運算式運算;
${}:
-
類似于Statement
-
正常情況下,跟#{}獲取引數的寫法沒有區別;
-
區別:不能隨意獲取引數,不能使用內置引數,必須起別名;
-
底層是字串拼接,不是占位符,不安全,當#{}解決不了,就必須使用${};
-
可以使用,動態表名,動態列名,運算式運算等;
建議:MyBatis的SQL映射檔案中,能優先使用#{},就必須使用,除非特殊情況,必須使用字串拼接,才可以使用${};
4.6.1 SQL
使用動態表名查詢動漫;
<!-- Anime selectProduceAndCid(@Param("produce") String produce,@Param("cid")Integer cid,@Param("tableName")String tableName); -->
<select id="selectProduceAndCid" resultType="com.kgc.mybatis.bean.Anime">
select `id`,
`cid`,
`name`
from ${tableName}
where `produce` = #{produce}
and `cid` = #{cid}
</select>
4.6.2 測驗
@Test
public void testMybatisMapperSelectParams5() throws IOException{
SqlSession sqlSession = getSqlSessionFactory().openSession();
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
Anime anime = animeMapper.selectProduceAndCid("騰訊動漫", 2, "animes");
System.out.println(String.format("4.集合引數 根據動漫編號:%d,查詢動漫詳情%s",anime.getId(),anime));
}
4.7 查詢多條資料
查詢多條資料, resultType 屬性值還是物體類;
resultType="com.kgc.mybatis.bean.Anime"
Mybatis會自己走 回傳集合的方法,自動將資料放到集合中;
//var1 select標簽的id屬性的值
<E> List<E> selectList(String var1);
//var2 為介面方法的引數
<E> List<E> selectList(String var1, Object var2);
//var3 為分頁物件
<E> List<E> selectList(String var1, Object var2, RowBounds var3);
4.7.1 SQL
<!-- List<Anime> selectAnimeListByCid(Integer Cid); -->
<select id="selectAnimeListByCid" resultType="com.kgc.mybatis.bean.Anime">
select `id`,
`cid`,
`name`
from `animes`
where `cid` = #{cid}
</select>
4.7.2 測驗
@Test
public void testMyBatisMapperSelectResults() throws IOException {
SqlSession sqlSession = getSqlSessionFactory().openSession();
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
//根據動漫分類編號查詢動漫
List<Anime> animeList = animeMapper.selectAnimeListByCid(3);
for (Anime anime : animeList) {
System.out.println(anime);
}
}
4.8 模糊查詢
使用 #{} 建議使用 concat('%',#{name},'%');
使用 ${name} 必須給引數起別名;
4.8.1 SQL
4.8.1.1 使用 #{name}
<!-- List<Anime> selectAnimeListByName(String name); -->
<select id="selectAnimeListByName" resultType="com.kgc.mybatis.bean.Anime">
select `id`,
`cid`,
`name`
from `animes`
<!-- where name like '%'#{name}'%'-->
where name like concat('%',#{name},'%')
</select>
4.8.1.2 使用${name}
<!-- List<Anime> selectAnimeListByName(@Param("name") String name); -->
<select id="selectAnimeListByName" resultType="com.kgc.mybatis.bean.Anime">
select `id`,
`cid`,
`name`
from `animes`
where name like '%${name}%'
</select>
使用${name} 如果不取別名, 取不到引數;
There is no getter for property named 'name' in 'class java.lang.String'
4.8.2 測驗
@Test
public void testMyBatisMapperSelectResults2() throws IOException {
SqlSession sqlSession = getSqlSessionFactory().openSession();
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
//根據動漫名稱 模糊 查詢動漫串列
List<Anime> animeList = animeMapper.selectAnimeListByName("魁");
for (Anime anime : animeList) {
System.out.println(anime);
}
}
4.9 分頁查詢
- 方法一:呼叫介面的時候,計算好分頁起始行,SQL中直接獲取引數((pageNo - 1)*pageSize),實作分頁;
- 方法二:使用 limit ${(pageNo - 1)*pageSize},#{pageSize} (不建議使用)
- 方法三:使用select的子標簽bind自定義屬性,<bind name="pageIndex" value="https://www.cnblogs.com/xiaoqigui/archive/2022/08/22/((pageNo - 1)*pageSize)"/>
4.9.1 SQL
<select id="selectAnimeListByProduce" resultType="com.kgc.mybatis.bean.Anime">
<bind name="pageIndex" value="https://www.cnblogs.com/xiaoqigui/archive/2022/08/22/((pageNo - 1)*pageSize)"/>
select `id`,
`cid`
from `animes`
where `produce` like concat('',#{produce},'%')
<!-- 方式一:$符進行計算 -->
<!-- limit ${(pageNo - 1)*pageSize},#{pageSize} -->
<!-- 方式2:bind,自定義引數 -->
limit #{pageIndex},#{pageSize}
</select>
4.9.2 測驗
@Test
public void testSelectAnimeListByProduce() throws IOException {
SqlSession sqlSession = getSqlSessionFactory().openSession();
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
//模擬獲取分頁引數
Integer pageNo = 1;
Integer pageSize = 3;
//呼叫mapper介面,模糊查詢,查詢分頁串列
//方法一:呼叫介面的時候,計算好分頁起始行,SQL中直接獲取引數,實作分頁
//方法二:使用 limit ${(pageNo - 1)*pageSize},#{pageSize}
//方法三:使用select的子標簽bind,<bind name="pageIndex" value="https://www.cnblogs.com/xiaoqigui/archive/2022/08/22/((pageNo - 1)*pageSize)"/>
List<Anime> animeList = animeMapper.selectAnimeListByProduce("愛奇藝",pageNo,pageSize);
animeList.forEach(System.out::println);
}
4.10 回傳Map集合
4.10.1 列名作為key,數值作為value
- 以動漫詳情為例模擬回傳map集合,將列名作為key,數值作為value;
- 實際開發中,查詢結果集,是單條記錄,且沒有物體對應,比如:資料統計,只有統計結果,沒有統計物體;
5.10.1.1 SQL
Map<String,Object>,方法的回傳型別是Map,key是String型別,value是Object型別,因為每個欄位有不同的型別;
resultType="java.util.HashMap",因為將資料映射到map中;
<!-- Map<String,Object> selectAnimeMapById(Integer id); -->
<select id="selectAnimeMapById" resultType="java.util.HashMap">
select `id`,
`cid`,
`name`
from `animes`
where `id` = #{id}
</select>
4.10.1.1 測驗
@Test
public void testSelectAnimeByMapById() throws IOException {
SqlSession sqlSession = getSqlSessionFactory().openSession();
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
Map<String, Object> animeMap = animeMapper.selectAnimeMapById(301);
System.out.println(animeMap);
Object actor = animeMap.get("actor");
System.out.println("actor==>"+actor);
}
4.10.2主鍵key,物體為value
- 以動漫詳情為例模擬回傳map集合,將資料主鍵列值作為key,整條資料作為value;
- 實際開發中回傳多條記錄,并需要根據key,快速遍歷,比如分組查詢;
4.10.2.1 SQL
因為它不知道你要將哪個屬性作為map的key值,所以需要@MapKey("id"),指定一個物體的屬性作為map的key值;
//以動漫詳情為例模擬回傳map集合,將資料主鍵列值作為key,整條資料作為value
@MapKey("id") //這里的MapKey 是物體的一個屬性
Map<Integer,Anime> selectAnimeMapByCid(Integer cid);
resultType="com.kgc.mybatis.bean.Anime",雖然回傳的結果是map,但是資料是映射到Anime動漫物體中;
<!-- @MapKey("id") //這里的MapKey 是物體的一個屬性 -->
<!-- Map<Integer,Anime> selectAnimeMapByCid(Integer cid); -->
<select id="selectAnimeMapByCid" resultType="com.kgc.mybatis.bean.Anime">
select `id`,
`cid`,
`name`
from `animes`
where `cid` = #{cid}
</select>
4.10.2.2 測驗
@Test
public void testSelectAnimeMapByCid() throws IOException {
SqlSession sqlSession = getSqlSessionFactory().openSession();
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
Map<Integer, Anime> animeMap = animeMapper.selectAnimeMapByCid(3);
System.out.println(animeMap);
Anime anime = animeMap.get(301);
System.out.println(anime);
}
5、ResultMap 結果集映射
5.1 列名 和 屬性名 不匹配
- 可以取別名,查詢出來的列名,取別名,跟物體的屬性名一致;
- 自定義resultMap映射;
5.1.1 SQL
| resultMap的引數 | 說明 |
|---|---|
| id | resultMap唯一id |
| type | 回傳值型別 |
| autoMapping | 是否開啟自動映射 |
resultMap自定義標簽內指定的列才會映射,如果查詢的結果列,不在自定義映射標簽中,但是滿足自動映射的條件(列名和物體屬性名一致), 仍然會自動映射;
除非指定resultMap標簽的autoMapping屬性為false(autoMapping="false"),沒有自定義映射的其他欄位才不會自動映射;
<!-- Anime selectAnimeByResultMap(Integer id); -->
<select id="selectAnimeByResultMap" resultMap="animeResultMap">
select `id`,
`cid`,
`name`,
`author`,
`actor`,
`produce`,
`create_date` `crateTime`
from `animes`
where `id` = #{id}
</select>
<!--
autoMapping="false" 關閉自動映射,只使用自定義映射;
-->
<resultMap id="animeResultMap" type="com.kgc.mybatis.bean.Anime" autoMapping="false">
<!-- 主鍵映射標簽 -->
<id column="id" property="id"></id>
<!-- 普通列映射標簽 -->
<result column="cid" property="cid"></result>
<result column="name" property="name"></result>
<result column="crateTime" property="createDate"></result>
</resultMap>
5.1.2 測驗
@Test
public void testSelectAnimeByResultMap() throws IOException {
SqlSession sqlSession = getSqlSessionFactory().openSession();
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
//使用自定義映射,查詢動漫詳情,解決列名和屬性名不同意的映射
Anime anime = animeMapper.selectAnimeByResultMap(301);
System.out.println(anime);
}
5.2 級聯映射
物體屬性,級聯映射;
5.2.1 一對一
級聯映射只適合一對一;
要求:查詢動漫Anime,并且查詢出動漫的 物體屬性category 的資訊;
一個動漫 對 一個動漫分類;
5.2.1.1 物體
動漫物體Anime
public class Anime {
//動漫編號
private Integer id;
//分類編號
private Integer cid;
//名稱
private String name;
......
//分類詳情物體,一對一 (也可以定義分類名稱冗余到物體中也可以解決)
private Category category;
}
分類物體Category
public class Category {
//分類編號
private Integer id;
//分類名稱
private String name;
}
5.2.1.2 SQL
<result column="cid" property="category.id"></result>
| 引數 | 說明 |
|---|---|
| column="cid" | 連表查詢出來的欄位 |
| property="category.id" | 物體屬性 的屬性 |
先通過連表查詢,將動漫資訊和分類資訊查詢出來,再根據欄位,一 一 映射;
<resultMap id="animeResultMapCascade" type="com.kgc.mybatis.bean.Anime" >
<!-- 主鍵映射標簽 -->
<id column="id" property="id"></id>
<!-- 普通列映射標簽 -->
<result column="cid" property="cid"></result>
<result column="name" property="name"></result>
<result column="author" property="author"></result>
<result column="create_date" property="createDate"></result>
<!-- 級聯映射,通過 內部物體屬性名.屬性 -->
<result column="cid" property="category.id"></result>
<result column="cname" property="category.name"></result>
</resultMap>
5.2.1.3 測驗
@Test
public void testSelectAnimeByResultMapCascade() throws IOException {
SqlSession sqlSession = getSqlSessionFactory().openSession();
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
//級聯映射,動漫物體內部,分類物體屬性的 級聯映射
Anime anime = animeMapper.selectAnimeByResultMapCascade(301);
System.out.println(anime);
//Anime(id=301,
// cid=3,
// name=完美世界,
// ......
// category=Category(id=3, name=科幻)
// )
}
5.3 關聯映射 (高級映射)
物體屬性,關聯映射;
5.3.1 association 一對一
要求:查詢動漫Anime,并且查詢出動漫的 物體屬性category 的資訊 ;
一個動漫 對 一個動漫分類;
5.3.1 物體
動漫物體Anime
public class Anime {
//動漫編號
private Integer id;
//分類編號
private Integer cid;
//名稱
private String name;
......
//分類詳情物體,一對一
private Category category;
}
分類物體Category
public class Category {
//分類編號
private Integer id;
//分類名稱
private String name;
}
5.3.2 SQL
先通過連表查詢,查詢出動漫資訊,和動漫分類資訊;
再通過association標簽,對動漫的 物體屬性 category 進行賦值;
<!-- Anime selectAnimeByResultMapAssociation(Integer id); -->
<select id="selectAnimeByResultMapAssociation" resultMap="animeResultMapAssociation">
select a.`id`,
a.`cid`,
a.`name`,
a.`author`,
a.`actor`,
a.`produce`,
a.`create_date`,
c.`name` 'cname'
from `animes` a,`category` c
where a.`cid` = c.`id`
and a.`id` = #{id}
</select>
<resultMap id="animeResultMapAssociation" type="com.kgc.mybatis.bean.Anime" >
<!-- 主鍵映射標簽 -->
<id column="id" property="id"></id>
<!-- 普通列映射標簽 -->
<result column="cid" property="cid"></result>
<result column="name" property="name"></result>
<result column="author" property="author"></result>
<result column="produce" property="produce"></result>
<result column="create_date" property="createDate"></result>
<!-- 關聯映射,內部物體一對一 -->
<association property="category" javaType="com.kgc.mybatis.bean.Category">
<id column="cid" property="id"></id>
<result column="cname" property="name"></result>
</association>
</resultMap>
5.3.3 測驗
@Test
public void testSelectAnimeByResultMapAssociation() throws IOException {
SqlSession sqlSession = getSqlSessionFactory().openSession();
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
Anime anime = animeMapper.selectAnimeByResultMapAssociation(301);
System.out.println(anime);
//Anime(id=301,
// cid=3,
// name=完美世界,
// ......
// category=Category(id=3, name=科幻)
// )
}
5.3.2 collection 一對多
要求:查詢分類Category,并且查詢出分類下的動漫集合屬性 animes 資訊;
一個動漫分類 對 多個動漫;
5.3.1 物體
分類物體Category
public class Category {
//分類編號
private Integer id;
//分類名稱
private String name;
//當前 分類下的 動漫集合
private List<Anime> animes;
}
動漫物體Anime
public class Anime {
//動漫編號
private Integer id;
//分類編號
private Integer cid;
//名稱
private String name;
......
}
5.3.2 SQL
先通過連表查詢,查詢出動漫分類資訊,和動漫資訊;
再通過collection標簽,對動漫分類的 集合屬性 animes 進行賦值;
<!-- Category selectCategoryByResultMapCollection(Integer id); -->
<select id="selectCategoryByResultMapCollection" resultMap="categoryByResultMapCollection">
select c.`id`,
c.`name`,
a.`id` 'aid',
a.`cid`,
a.`name` 'aname',
a.`author`,
a.`actor`,
a.`create_date`,
a.`produce`
from `category` c,`animes` a
where c.`id` = a.`cid`
and c.`id` = #{id}
</select>
<resultMap id="categoryByResultMapCollection" type="com.kgc.mybatis.bean.Category">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<!-- 高級映射,使用集合 關聯映射,解決內部集合映射,一對多 -->
<collection property="animes" ofType="com.kgc.mybatis.bean.Anime">
<id column="aid" property="id"></id>
<result column="cid" property="cid"></result>
<result column="aname" property="name"></result>
<result column="author" property="author"></result>
<result column="actor" property="actor"></result>
<result column="produce" property="produce"></result>
<result column="create_date" property="createDate"></result>
</collection>
</resultMap>
5.3.3 測驗
@Test
public void testSelectCategoryByResultMapCollection() throws IOException {
SqlSession sqlSession = getSqlSessionFactory().openSession();
CategoryMapper categoryMapper = sqlSession.getMapper(CategoryMapper.class);
//查詢動漫分類詳情,內部集合型別 映射
Category category = categoryMapper.selectCategoryByResultMapCollection(3);
System.out.println(category);
//Category(id=3,
// name=科幻,
// animes=[Anime(id=301, cid=3, name=完美世界, ...),
// Anime(id=649, cid=3, name=蠟筆小新, ...)
// ]
// )
}
5.4 嵌套select, 延遲加載 和 分步查詢
- 開啟延遲加載,默認false,需要支持延遲,改為true;
- <setting name="lazyLoadingEnabled" value="https://www.cnblogs.com/xiaoqigui/archive/2022/08/22/true"></setting>
- 按需加載 ,是否全部加載,
- (前提必須是言辭加載是打開的,而且是自定義映射,配合高級嵌套select查詢);
- 在3.4.1及之前的版本中默認為true,全部加載(任意一方法的呼叫都會加載該物件的所有延遲加載屬性);
- 只有改為false,才會分步加載,需要呼叫該方法時,才進行 延遲加載屬性;
- <setting name="aggressiveLazyLoading" value="https://www.cnblogs.com/xiaoqigui/archive/2022/08/22/false"/>
5.4.1 association 一對一
要求:查詢動漫Anime,并且查詢出動漫的 物體屬性category 的資訊 ;
一個動漫 對 一個動漫分類;
5.4.1.1 物體
跟 關聯映射 association 一對一 的物體一樣;
5.4.1.2 SQL
<association property="category" select="com.kgc.mybatis.mapper.CategoryMapper.selectCategoryById" column="cid" fetchType="eager">
</association>
| 引數 | 說明 |
|---|---|
| property | 物體的屬性 |
| select | 指定嵌套的select陳述句的唯一標識 |
| column | 指定嵌套的sleect陳述句執行需要的引數,多引數JSON格式{key1=col1,key2=col2} |
| fetchType | 是否適配系統延遲加載,默認是lazy,如果需要區域關閉延遲加載,改為eager |
先通過id查詢動漫Anime,再通過動漫的cid,去查詢 動漫分類;
AnimeMapper.xml
<!--Anime selectAnimeByResultMapAssociationLazyLoadingStep(Integer id);-->
<select id="selectAnimeByResultMapAssociationLazyLoadingStep" resultMap="associationLazyLoadingStep">
select `id`,
`cid`,
`name`,
`author`,
`actor`,
`produce`,
`create_date` `crateTime`
from `animes`
where `id` = #{id}
</select>
<!-- 嵌套select陳述句實作 延遲加載 和 分布查詢 -->
<resultMap id="associationLazyLoadingStep" type="com.kgc.mybatis.bean.Anime">
<!-- 主鍵映射標簽 -->
<id column="id" property="id"></id>
<!-- 普通列映射標簽 -->
<result column="cid" property="cid"></result>
<result column="name" property="name"></result>
<result column="author" property="author"></result>
<result column="produce" property="produce"></result>
<result column="crateTime" property="createDate"></result>
<!-- 高級映射,內部物體一對一 ,嵌套select陳述句, 延遲加載和分布查詢 -->
<!-- fetchType="eager" 區域覆寫按需加載 -->
<!--
select屬性,指定嵌套的select陳述句的唯一標識(myabtis框架可識別的)
column屬性:指定嵌套的sleect陳述句執行需要的引數,即將當前查詢某列的值作為引數,傳遞到指定的查詢陳述句中,如果有多個引數,可以使用JSON格式{key1=col1,key2=col2}
fetchType屬性:設定當前自定高級映射是否適配系統延遲加載,默認是lazy,如果需要區域關閉延遲加載,改為eager
-->
<association property="category" select="com.kgc.mybatis.mapper.CategoryMapper.selectCategoryById" column="cid" fetchType="eager">
</association>
</resultMap>
CategoryMapper.xml
<!-- Category selectCategoryById(Integer id); -->
<select id="selectCategoryById" resultType="com.kgc.mybatis.bean.Category">
select `id`,
`name`
from `category`
where `id`= #{id}
</select>
5.4.1.3 測驗
@Test
public void testSelectAnimeByResultMapAssociationLazyLoadingStep() throws IOException {
SqlSession sqlSession = getSqlSessionFactory().openSession();
AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
//高級映射,內部物體一對一 ,使用嵌套select 延遲加載和分布查詢
Anime anime = animeMapper.selectAnimeByResultMapAssociationLazyLoadingStep(301);
System.out.println("如果只使用動漫的資訊,不使用加載 動漫分類的SQL");
System.out.println(anime.getName());
System.out.println("=============================================");
System.out.println("動漫的分類名稱:"+anime.getCategory().getName());
}
開啟延遲加載和按需加載

關閉延遲加載和按需加載,或者區域關閉延遲加載

5.4.2 collection 一對多
要求:查詢分類Category,并且查詢出分類下的動漫集合屬性 animes 資訊;
一個動漫分類 對 多個動漫;
5.4.2.1 物體
跟 關聯映射 collection 一對多 的物體一樣;
5.4.2.2 SQL
先通過id查詢分類Category,再通過動漫的id,去查詢cid等于id的動漫;
CategoryMapper.xml
<!--Category selectCategoryByResultMapCollectionAssociationLazyLoadingStep(Integer id); -->
<select id="selectCategoryByResultMapCollectionAssociationLazyLoadingStep" resultMap="associationLazyLoadingStep" >
select `id`,
`name`
from `category`
where `id`= #{id}
</select>
<resultMap id="associationLazyLoadingStep" type="com.kgc.mybatis.bean.Category">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<!-- 高級映射,使用集合映射,解決內部 集合映射,一對多 -->
<collection property="animes" select="com.kgc.mybatis.mapper.AnimeMapper.selectAnimeListByCid" column="{cid=id}" fetchType="lazy">
</collection>
</resultMap>
AnimeMapper.xml
<!-- Map<Integer,Anime> selectAnimeMapByCid(Integer cid); -->
<select id="selectAnimeMapByCid" resultType="com.kgc.mybatis.bean.Anime">
select `id`,
`cid`,
`name`,
`author`,
`actor`,
`produce`,
`create_date`
from `animes`
where `cid` = #{cid}
</select>
5.4.2.3 測驗
@Test
public void testSelectCategoryByResultMapCollectionAssociationLazyLoadingStep() throws IOException {
SqlSession sqlSession = getSqlSessionFactory().openSession();
CategoryMapper categoryMapper = sqlSession.getMapper(CategoryMapper.class);
Category category = categoryMapper.selectCategoryByResultMapCollectionAssociationLazyLoadingStep(1);
System.out.println("分類名稱:"+category.getName());
System.out.println("=============================================");
System.out.println("該分類下的動漫:"+category.getAnimes());
}
開啟延遲加載和按需加載

關閉延遲加載和按需加載,或者區域關閉延遲加載

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/502446.html
標籤:其他
上一篇:快速掌握 Base 64 | Java JS 密碼系列
下一篇:Java基礎學習筆記(2)
