1、insert 標簽 1.1 獲取SqlSessionFactory 對象的通用方法 方便後面分測試; //獲取SqlSessionFactory 對象的通用方法 public SqlSessionFactory getSqlSessionFactory() throws IOException ...
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="((pageNo - 1)*pageSize)"/>
4.9.1 SQL
<select id="selectAnimeListByProduce" resultType="com.kgc.mybatis.bean.Anime">
<bind name="pageIndex" value="((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="((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="true"></setting>
- 按需載入 ,是否全部載入,
- (前提必須是言辭載入是打開的,而且是自定義映射,配合高級嵌套select查詢);
- 在3.4.1及之前的版本中預設為true,全部載入(任意一方法的調用都會載入該對象的所有延遲載入屬性);
- 只有改為false,才會分步載入,需要調用該方法時,才進行 延遲載入屬性;
- <setting name="aggressiveLazyLoading" value="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());
}
開啟延遲載入和按需載入
關閉延遲載入和按需載入,或者局部關閉延遲載入