Sql檔案映射
這裡隻是筆記,屬性詳情,關鍵還是要多練 ——執行個體代碼
MyBatisDemo
MyBatis 真正的強大在于映射語句,專注于SQL,功能強大,SQL映射的配置卻是相當簡單
SQL映射檔案的幾個頂級元素
name | 詳情 |
---|---|
mapper | namespace: 命名空間 |
cache | 配置給定命名空間的緩存 |
cache-ref | 從其他命名空間引用緩存配置 |
resultMap | 用來描述資料庫結果集和對象的對應關系 |
sql | 可以重用的SQL塊,也可以被其他語句引用 |
insert | 映射插入語句 |
update | 映射更新語句 |
delete | 映射删除語句 |
select | 映射查詢語句 |
:--------: | -------------: |
-
mapper
namespace:命名空間: 一般引用對應的接口類位址,也可以随便起名,如果面向接口程式設計則必須要是對應接口的位址引用…
namespace和子元素的id聯合保證唯一,接口中的方法與映射檔案中的sql 語句 一一對應;
<mapper namespace="命名空間">
<select id="login" …
……
</select>
</mapper>
-
Select
select是MyBatis中最常用的元素之一, 用于查詢 sql 操作;
select語句有很多屬性可以詳細配置每一條語句
常用屬性
id
命名空間中唯一的辨別符可随意 但如果是 面向接口程式設計 方法名與映射檔案中的SQL語句 id 一 一 對應(要相同);
parameterType
傳入SQL語句的參數類型,
基礎資料類型: int、String、 Date等隻能傳入一個,通過 #{随意參數名} 即可擷取傳入的值; 這裡參數名可以随意… 因為參數隻有一個無須細分了~
複雜資料類型: Java實體類、Map等通過 #{屬性名} 或者 #{map的keyName} 即可擷取傳入值; Map可用于多個參數;
resultType
SQL語句傳回值的類型 與
parameterType
類似, 可以是基礎或複雜資料類型…
MyBatis中resultType自動映射, 字段名 和 屬性名必須一緻才可以哦~
注意: 傳回結果如果是 實體類類型,盡量類屬性名 與資料庫列名一緻,不然會很麻煩哦~
resultMap
命名引用外部的resultMap
flushCache
将其設定為true,不論語句什麼時候被調用,都會導緻緩存被清空。預設值:false
useCache
将其設定為true,将會導緻本條語句的結果被緩存。預設值:true
timeout
這個設定驅動程式等待資料庫傳回請求結果,并抛出異常時間的最大等待值。預設不設定(驅動自行處理)
fetchSize
這是暗示驅動程式每次批量傳回的結果行數
…
-
resultMap
上面查詢結果類型是 User類型, 但如果資料庫列名與實體類的屬性名, 不一緻,MyBatis 檔案映射不出來:
而可以通過SQL 語句查詢,列起别名形式進行, 改正:
但還是不好,而且 兩表連接配接查詢時候, Java一般會在實體類中存在另一個類型對象…這個怎麼解決呢~
eg: 檢視使用者及使用者的部門資訊… 使用者表/部門表; 而兩表連接配接需要存部門的資訊; 使用者有部門屬性,是以一般實體類 會放一個部門類的對象… 這就可以使用
resultMap
;
常用屬性
id
唯一辨別,id 值用于select元素 resuMap的引用;
type
表示resultMap的映射結果;
id 标簽
子節點:< id property="屬性名“ column=”主鍵列名“ /> 一般一個resultMap 隻有一個表示查詢的主鍵列,提高程式效率; 如果需要查詢多個資料時, !不然你永遠隻會查到一條資料!
吃過虧的我...可别學我
至于為啥:
resultMap中如果不定義類似主鍵之類的能夠區分每一條結果集的字段的話,會引起後面一條資料覆寫前面一條資料的現象。
result:
子節點:用于辨別屬性,< result property="屬性名“ column=”列名“ /> 如果查詢時候有些屬性應該有值,結果卻是 null 就是沒有映射上!或 映射級别過低…
assoction
子節點: A表 B表, 兩表連接配接… A類存在B類型對象屬性; 就需要使用 assoction 進行映射;
assoction 處理 ”一對一“ 的關聯關系; w是人事部 s是技術部…
property:表示在A類中的屬性名; javaType : 表示該屬性的類名; …
collection
同 assoction 類似, assoction表示 一對一, 而 collection 則表示 一對多;
即:查詢人事部的所有員工; Java的部門類中就需要一個使用者集合…
關于映射級别
可以在MyBatis-config.xml 中 < setting name=“auto<appMappingBehavior” value=“PARTIAL” />
NONE : 禁止自動映射;
PARTIAL : 預設值,允許自動映射; 但 collection/assoction 子元素中,無法自動映射;——級别不夠
FULL :更進階的映射, 允許 collection/assoction 子元素中自動映射;
最後,最後 還要注意的是: 資料庫列一定要和實體類類對應!
sql語句多表檢視不要出現相同的列名(
) ,實體類的資料類型 要注意! 與資料庫的值可以比對的:這個問題不大
Error getting nested result map values for 'sort'. Cause: java.sql.SQLException: Invalid value for getInt() - '鏂囧叿'
一定注意!中:擷取“sort”的嵌套結果映射值時出錯。 無效的值 getInt() '鏂囧叿'————這是我報的錯真的是坑死了!實體類是 int 資料庫是 字元串!!!
SQL映射
UserMapper.xml
<!-- 面向接口 -->
<!--
resultMap元素屬性和子節點:
id: 唯一辨別,此ID 用于select元素 resultMap 屬性的引用;
type: 表示resultMap 映射的類型;
result: 子節點 property類屬性 column庫列名 進行一一對應,解決了名字不比對問題;
resultMap 與 resultType 的關聯:
resultType: 直接表示傳回結果類型,包括基本資料類型 和 複雜資料類型;
resultMap: 則是對外部 resultMap 定義的引用,它的場景一般是 資料庫字段與實體類屬性名不一緻使用; 或 兩表連接配接A類存在B類型對象;
關聯: MyBatis進行查詢映射時候,其實查詢出來的字段值都放在一個對應的Map裡面,key字段名 value值;
select 設定 resultType 時,傳回結果也是Map 結構,而底層将 Map的值取出來進行 resultType類型的 setter(xx);進行指派了; 是以需要get/set!别忘了哦!
resultType resultMap 本質上都是 Map 資料結構, 兩者不可以同時在一個 select 中使用哦~;
-->
<resultMap type="User" id="userMap">
<!-- property類屬性 column庫列名 MyBatis也會對 資料庫/實體列 相同的進行一一映射,不一緻的就需要手動進行映射了; -->
<id property="id" column="id" />
<result property="userCode" column="userCode" />
<!-- ...還好我這兒與資料庫都一樣就不需要一一映射了 -->
<association property="role" javaType="Role" >
<!-- <result property="xxx" column="xxx" /> -->
<!-- ...還好我這兒與資料庫都一樣 且MyBatis: setting 設定 autoMappingBehavior 屬性級别 FULL 就不需要一一映射了 -->
</association>
</resultMap>
<!--MyBatis-config.xml setting 設定resultMap的自動映射級别,NONE(禁止自動比對),PARTIAL(預設)自動比對所有屬性,有内部嵌套(association、collection)的除外,FULL(自動比對所有屬性) -->
<!-- 面向接口形式, id 要與接口的方法名相同; -->
<!-- 接口參數使用了 Java注解是以,映射檔案這裡就不需要,parameterType參數類型了, #{注解名} 找到對應注解值; -->
<select id="login" resultMap="userMap" >
SELECT su.*,sr.`roleName` FROM `smbms_user` su ,`smbms_role` sr WHERE su.`userRole` = sr.`id` AND su.`userName`= #{name} AND su.`userPassword` = #{pwd}
</select>
Java接口:
UserMapper.Java
@Param 注解實作多參數
// 有時候, 參數需要很多可以使用 parameterType 的 Map Java實體類 但還是比較麻煩~ 還可使用Java 注解來解決…
// 隻需要在定義接口時候在參數清單,需要的參數使用:
@Param(" sql中使用的name ")參數類型 參數名
即可;
public interface UserMapper {
//登入方法,根據使用者名/密碼使用者登入,并顯示使用者部門名稱.. 兩表連接配接.. assoction;
public User login(@Param("name")String name,@Param("pwd")String pwd); //使用了: 注解形式傳參;
}
注意
mybatis傳單個類型參數,可以不用@param注解,前提是xml中不含有 條件表達式(when,if..動态标簽中沒有引用到該參數) 大忌!!
映射檔案代碼片段~
<!-- 動态SQl 後面文章有詳細講解~ -->
<!-- 單個參數如果參數不加 @param if/where/..中是無法使用的..大忌!(當時找了好久~) -->
<if test="w !=null and w != ''">
<!-- 通過 #{w} 方式引入單個參數的值,拼接動态SQL -->
</if>
運作類
Run.Java
public User login(String name,String pwd){
SqlSession session = MyBatisUtil.createSqlSession();
UserMapper um = session.getMapper(UserMapper.class);
User u = um.login(name, pwd);
MyBatisUtil.closeSqlSession(session);
return u;
}
-
collection 一對多;
根據部門ID查部門,及其所有員工
SQL映射
RoleMapper.xml
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/> <!-- 二級緩存 -->
<!--
eviction :檔案的儲存形式;
flushInterval :緩存對象的毫秒數;
size :緩存對象的個數; 先進先出原則,如果已經滿了,則最先進的移除,添加新的
readOnly : 隻讀
-->
<resultMap type="Role" id="RoleMap">
<result property="id" column="id" />
<collection property="users" ofType="User" >
<!-- ...還好我這兒與資料庫都一樣 且MyBatis: setting 設定 autoMappingBehavior 屬性級别 FULL 就不需要一一映射了 -->
</collection>
</resultMap>
<select id="cha" resultMap="RoleMap" useCache="true" >
SELECT rs.*,us.`userName` FROM `smbms_role` rs ,`smbms_user` us WHERE rs.`id` = us.`userRole` AND rs.`id`=#{id};
</select>
Java接口
RoleMapper.Java
//根據部門id檢視部門資訊,及該部門的所有員工
public Role cha(@Param("id")int id);
運作類
Run.Java
//根據編号查部門及 部門員工;
public void bmcha(){
SqlSession session = MyBatisUtil.createSqlSession();
RoleMapper rm = session.getMapper(RoleMapper.class);
//一級緩存:緩存資料存儲在 sqlSession中;
Role r = rm.cha(1);
System.out.println(r.getRoleName()+"\t"+r.getId());
List<User> u = r.getUsers();
for (User user : u) {
System.out.println(user.getUserName());
}
MyBatisUtil.closeSqlSession(session);
}
-
insert
insert完成新增操作;
增 删 改 : 會對資料庫造成影響, 屬于事務. 是以在 MyBatisUtil 類中
SqlSessionFactory.openSession(false); // 參數false表是開啟事務控制,不傳參數表示預設為true(為自動送出事務)
如果是false 則記住需要手動送出事務哦, 不然資料不會改變哦;
常用屬性
id
parameterType同上
//一般隻有查詢,有傳回結果… 增 删 改 差不多都一緻。。。同上
SQL映射
UserMapper.xml
<!-- 新增 -->
<!-- 面向接口形式, id 要與接口的方法名相同; -->
<insert id="xz" parameterType="User" >
INSERT into `smbms_user` values
(null,#{userCode},#{userName},#{userPassword},1,'1983-10-10','13688889999','北京市東城區前門東大街9号',2,1,'2020-08-18 09:56:31',NULL,NULL);
</insert>
Java接口:
UserMapper.Java
public interface UserMapper {
//新增
public int xz(User u);
運作類
Run.Java
public void addxz(){
//新增的User 對象;
User us = new User();
us.setUserCode("WSM");
us.setUserName("wangX");
us.setUserPassword("540707");
SqlSession session = MyBatisUtil.createSqlSession();
int jg = 0;
try {
//采用面向接口方法
//sqlSession.getMapper(接口類.Class); 前提是映射檔案命名空間指向接口的位址;
// 且映射檔案對應的ID名要 和 接口的方法名相同;
// Mybatis 底層實作了UserMapper接口,并傳回了對應執行個體,友善調用起對應方法;
// 好處,不用在在意 SqlSession 的增删改查的方法: selectone(); insert();...方法了; 可以根據,自定義的方法來實作 "增删改查..操作";
UserMapper um = session.getMapper(UserMapper.class);
//傳回影響行數
jg = um.xz(us);
session.commit(); //手動送出事務
// 注意增删改查操作; 需要送出,雖然資料庫進行了新增,但是事務還沒結束,根據事務原子性; 成功/失敗;
} catch (Exception e) {
e.printStackTrace();
session.rollback(); //出現異常,事務復原;
}finally{
MyBatisUtil.closeSqlSession(session);
if(jg==1){
System.out.println("新增成功");
}else{
System.out.println("新增失敗");
}
}
};
-
Update
Update完成修改操作;
SQL映射
UserMapper.xml
<!-- 修改 -->
<update id="xiugai" >
UPDATE `smbms_user` SET `userName` =#{name} WHERE `id` =#{id}
</update>
Java接口:
UserMapper.Java
//修改 根據角色ID 修改角色姓名;
public int xiugai(@Param("id")int id,@Param("name")String name);
運作類
Run.Java
public void upd(){
System.out.println("請輸入要修改使用者id");
int id = input.nextInt();
System.out.println("請輸入修改後使用者name");
String name = input.next();
SqlSession session = MyBatisUtil.createSqlSession();
try {
UserMapper um = session.getMapper(UserMapper.class);
if(um.xiugai(id, name)==1){
session.commit(); //成功送出事務
System.out.println("成功");
}else{
System.out.println("失敗");
}
} catch (Exception e) {
e.printStackTrace();
session.rollback();
}finally{
MyBatisUtil.closeSqlSession(session);
}
}
- delete 完成删除操作
SQL映射
UserMapper.xml
<!-- 删除 -->
<delete id="del" parameterType="int" >
DELETE FROM `smbms_user` WHERE id=#{del} <!-- 參數隻有一個可以随意一點了.. -->
</delete>
Java接口:
UserMapper.Java
//删除 根據角色Id 删除;
public int del(int id);
運作類
Run.Java
public void del(){
System.out.println("請輸入要删除ID");
int id = input.nextInt();
SqlSession session = MyBatisUtil.createSqlSession();
try {
UserMapper um = session.getMapper(UserMapper.class);
if(um.del(id)==1){
session.commit(); //成功送出事務
System.out.println("成功");
}else{
System.out.println("失敗");
}
} catch (Exception e) {
e.printStackTrace();
session.rollback();
}finally{
MyBatisUtil.closeSqlSession(session);
}
}
這裡隻是筆記,屬性詳情,關鍵還是要多練 ——執行個體代碼
MyBatisDemo
加油!奧利
碩!