天天看點

SSM-Mybatis的Mapper.xml配置檔案Mybatis的Mapper.xml配置檔案

Mybatis的Mapper.xml配置檔案

官方教學

常用标簽

這個檔案主要就是存儲sql語句的 結構在使用流程裡有 這裡就不寫了 直接來說他裡的 常用的sql标簽和用途

select标簽 用于查詢資料

insert标簽 用于添加資料

update标簽用于修改資料

delete标簽用于删除資料

​ parameterType參數類型 (可以指定 可以不指定 ) resultType傳回類型 如果傳回是實體類 (如果實體類那個包在核心配置檔案中聲明過了直接類名就行 否則需要包路徑.類名)

#{} 擷取傳進來的參數

  1. 必須和接口中方法參數名稱一緻 或者@Param 注解名一緻
  2. 必須和實體類中的 屬性名一緻
  3. 必須和Map中的key一緻
  4. 沒有使用parameterType指定擷取的參數類型那麼預設擷取方法中的參數[要和接口方法的變量名一緻]
  5. #{user_ok.name} 還可以這樣擷取實體類中屬性對象内的屬性(get set) user_ok是是實體類中的屬性名稱

查詢

<!--查詢全部資料條數-->
<select id="count" resultType="int" >
           select count(*) from product
</select>
<!--    查詢指定資料的條數-->
<select id="getBybooksCount" parameterType="String" resultType="int">
        select  count(name) from books 
        where name=#{name}
</select>

<!--    根據使用者名稱查詢使用者清單  (模糊查詢) 單參(8大資料類型)-->
 <select id="getUserListByUserName" parameterType="String" resultType="User">
        select * from xingxi
        where user like CONCAT('%',#{username},'%')
 </select>

<!--  根據使用者名稱查詢使用者清單 多參 實體類  -->
 <select id="getUserList_duocan" resultType="User" parameterType="User">
        select * from xingxi
        where user like CONCAT('%',#{user},'%')
        and name =#{name}
 </select>

    <!--  根據使用者名稱查詢使用者清單 多參Map   -->
<select id="getUserList_duocan_Map" parameterType="Map" resultType="User">
        select * from xingxi
        where user like CONCAT('%',#{uUser},'%')
        and name =#{uName}
</select>


           

增加

<!--向資料庫插入 資料 自增可以使用defaule代替的-->
<insert id="add" parameterType="User">
insert into xingxi (user,pass,name)value(#{user},#{pass},#{name})
</insert>


<!--    添加資料的同時傳回 插入資料的id (固定寫法) 在插入資料後 
他會自動将id存入到,你添加時候傳入的對象中的id屬性中
-->
<insert id="addBooks" parameterType="books">
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            select LAST_INSERT_ID()
        </selectKey>
        insert into books values (default ,#{name},#{price},#{id_type})
</insert>


	<!--    添加資料前 候自動生成36位字元串uuid(固定的寫法) 在添加資料前 插入到指定屬性裡 在實體類中要有此屬性-->
    <insert id="addBooksUUiD" parameterType="books">
        <selectKey keyProperty="uuid" order="BEFORE" resultType="String">
            select uuid()
        </selectKey>
        insert into books values (default ,#{name},#{price},#{id_type},#{uuid})
    </insert>


           

有的時候可能會用到一次插入多條那麼就可以這樣

<insert id="insertMoreMods" parameterType="java.util.ArrayList">
		insert into product_mods (product_id,module_type,mac,imei,imsi)
		values
		<!-- collerction:表示需要周遊的類型基本上隻有:list,array,Map這三中寫法。
			index:表示循環的下标。
			separator:表示每個對象的分隔符(也是進行下一次循環的辨別符)。
			item:表示目前循環對象。
			open:以什麼開頭。
			close:以什麼結尾。 -->
		<foreach collection="list" index="index" separator="," item="item">
			(#{item.productId},#{item.moduleType},#{item.mac},#{item.imei},#{item.imsi})
		</foreach>
	</insert>
           

接口

/**
	 * 向modes表中同時添加多條資料
	 * @param productModLists
	 * @return
	 */
	public int insertMoreMods(List<ProductMods> listProductMods); 
           

插入技巧: 使用 ignore ,為防止主鍵沖突,使用ignore關鍵字,若插入失敗不會抛異常,而是傳回插入成功的條數為0。

<insert id="insertSuccessKilled">
        <!--當出現主鍵沖突時(即重複秒殺時),會報錯;不想讓程式報錯,加入ignore-->
        INSERT ignore INTO success_killed(seckill_id,user_phone,state)
        VALUES (#{seckillId},#{userPhone},0)
    </insert>
           

修改

<!--    修改資料庫 資料-->
<update id="modify" parameterType="User">
update xingxi set user=#{user},pass=#{pass},name=#{name}
 where user=#{user_up}
</update>
<!--    修改資料庫 資料 擷取方法的參數 名稱要對應-->
<update id="updatePwd">
update xingxi set pass=#{pass}
 where user=#{user}
</update>

           

一般修改都是配合set和if 标簽使用

update `t_quote`
<set>
<if test="businessName !=null "> `business_name` =#(businessName},</if>
<if test="communityBusiness !-null"> `community-business` = #{communityBusiness}</if>
</set>
where id={id}                                                    
           

注意在修改時候的if 不要寫成下面這種

因為有些時候前端某些隻本來就不是必選項,傳遞到後端就是空的那麼就會導緻被過濾掉了,沒有進行修改

我在公司使用上面的if發生一個問題,就是修改時候,前端發送除了條件id外其他字段全部為空的對象,導緻最後sql報錯,因為最後系統拼接sql後發現沒有一行set 最後拼接sql如下:

這樣的sql肯定報錯的,因為set後啥都沒有,文法報錯

解決辦法: 一般修改都是通過id進行的 那麼我們可以把where查詢條件id 放入到set 裡,這樣就避免了 空set

update `t_quote`
<set>
<if test="id !=null "> `id` =#(id},</if>
<if test="businessName !=null "> `business_name` =#(businessName},</if>
<if test="communityBusiness !-null"> `community-business` = #{communityBusiness}</if>
</set>
where id={id}     

           

删除

<delete id="deleteUser" parameterType="String">
        DELETE FROM xingxi where user=#{user}
</delete>
<delete id="deleteUser" parameterType="Integer">
        DELETE FROM xingxi where id=#{id}
</delete>
           

在有些時候可能用到同時删除多條資料的情況

<delete id="deleteAudioAudioFiles" parameterType="java.util.ArrayList"  >
			delete from
			t_audio
			where audio_file in
			<foreach collection="list" item="item" open="(" separator="," close=")">
				#{item}
			</foreach>
		</delete>
           

接口

實體類映射

resultMap 手動映射實體類屬性 和 資料庫字段

注意  實體類中屬性和資料庫中字段不同的可以使用 如果相同的可以省略,當然如果出現查詢空字段那麼你還是要指定的
           

使用resultMap的幾種情況:

第一種就是:你不想使用資料庫字段 來作為屬性名稱

第二種 多表 一對一 查詢

第三種 多表 一對多查詢

注意隻要是使用了resultMap那麼必須全部屬性進行映射 否則沒有映射的屬性傳回null

id 标簽 資料庫主鍵id字段映射

property對應實體類中的屬性 column對應資料庫字段(可以别名)

result 标簽 普通字段映射

property對應實體類中的屬性 column對應資料庫字段(可以别名)

association 标簽 對象屬性映射

property 對應實體類中的對象屬性 javaType 類名 resultMap id

collection标簽 List集合對象 映射

property 對應實體類中的List對象屬性 ofType 類名 resultMap id
<!--  實體類映射-->
public class Entity {
 private Integer No;
 private String Name;
.... get set
  ...toString
}
<resultMap id="userList" type="Entity">
            <result property="No" column="no1"/>
            <result property="Name" column="SubjectName"/>
</resultMap>
<select id="getUserResultMap" resultMap="userList">
        select SubjectNo as no1 ,SubjectName from subject
</select>

對應接口:  public List<Entity>  userList();
    

           

不同mapper.xml 裡的 resultMap之間是能通過 Mapper的命名空間.resultMap的id就行了

一般用于 一對一 或者 一對多的 時候 調用其他Mapper 的resultMap

比如:

<association 
property="quoteLocationDo"
javaType="com.chinare.brp.biz.biz.domain.OuoteLocationDo"
resutMap="com.chinare.brp.biz.biz. dao.QuoteLocationDao.QuoteLocationDOMap"/>
           

當然其他mapper.xml 裡的方法也能應用,比如使用 collection 裡的select 也可以通用上面的方式進行引用

<collection 
property="businessFileReinsuranceDos" 
javaType="java.util. ArrayList" 
ofType="com.chinare.brp.biz.biz.domain.BusinessFiLepo" 
column="quote_id"
select="com.chinare.brp.biz.biz.dao.BizBusinessDao.getBusinessFileReinsuranceDos"/>
           

還可以進行繼承(相當于子resultMap兼用自身和父resultMap的)

利用resultMap的extends屬性。

<resultMap id="CocBeanResult" type="CocBean">
    <result property="name" column="NAME"/>
    <result property="volume" column="VOLUME"/>
</resultMap>
 
<resultMap id="simpleRow" type="CocTreeNode" extends="CocBeanResult">
    <result property="level1" column="LEVEL1"/>
    <result property="level2" column="LEVEL2"/>
</resultMap>
           

一對一, 和一對多

多表查詢:
    public class User {
    private Integer id;
    private String  user;
    private String  pass;
    private  User_xx user_xx;//一對一
    private List<User_xx> user_xx_list; //一對多
    .... get set
    ...toString
    }
    
   public class User_xx {

    private Integer u_id;
    private String  name;
    private Integer age;
    private Integer sex;
    private Integer xx_id;
     .... get set
    }
    

<!--    一對一   多表 查詢記錄 
注意: 一對一關系,除了主鍵ID和關聯ID的資料庫字段名稱可以一樣 ,其他字段都不能一樣 ,否則主表資料将覆寫到子表,如果類型不同的話就直接報錯了
-->
  
    <resultMap id="UserMa" type="User">
        <id property="id" column="id"/>
        <id property="user" column="user"/>
        <id property="pass" column="pass"/>
    <association property="user_xx" javaType="User_xx" resultMap="User_xxMap"/>
    </resultMap>
        
     <resultMap id="User_xxMap" type="User_xx">
        <id property="xx_id" column="xx_id" />
        <result property="u_id" column="u_id"/>
        <result property="name" column="name"/>
        <result property="age" column="age"/>
        <result property="sex" column="sex"/>
    </resultMap>       
        

    <select id="selRe"  resultMap="UserMa">
        SELECT * from user_mm as a,user_xx as b 
        WHERE a.id=b.u_id 
    </select>


對應接口: public List<User> selRe();
    
        
        
 還可以這樣 通過子查詢   以下的實體類就不展示了  按照上面的改下就行了
 唯一差別就是 javaType換成   column       resultMap換成select   實體類的屬性名不一樣
column 的值就是主表查詢出來的id給子查詢  寫是資料庫的字段名稱
select 的值 就是子值查詢的id名稱
然後子語句直接#{id}  就能擷取到傳進來的值 和名稱沒有關系
        
        

        <!--    一對一 -->
    <resultMap id="prodMap" type="product">
     	 <id property="id" column="id"/>
        <collection  property="type" column="type_id" select="show1Select">
    <!-- 子查詢 如果實體類的屬性和 資料庫字段一緻就不用手動映射-->
        </collection >
    </resultMap>
        
        
      <select id="show" resultMap="prodMap" parameterType="int" >
          select * from product
      </select>
        
    <select id="show1Select" resultType="product_type">
        select * from product_type where id=#{id}
    </select>
        
        


<!--    一對多  查詢 條記錄-->

        
    <resultMap id="UserMap" type="User">
        <id property="id" column="id"/>
        <id property="user" column="user"/>
        <id property="pass" column="pass"/>
    <collection property="user_xx_list" ofType="User_xx" resultMap="User_xxMap"/>
    </resultMap>
        
    <resultMap id="User_xxMap" type="User_xx">
        <id property="xx_id" column="xx_id" />
        <result property="u_id" column="u_id"/>
        <result property="name" column="name"/>
        <result property="age" column="age"/>
        <result property="sex" column="sex"/>
    </resultMap>
        
        

    <select id="selRe"  resultMap="UserMap">
    SELECT * from user_mm as a,user_xx as b
    WHERE  b.u_id in(select id from user_mm where user='hu'and pass='123')
    and a.id=b.u_id
    </select>
    
對應接口:  public User selRe();    
        
還可以這樣 通過子查詢   以下的實體類就不展示了  按照上面的改下就行了
 唯一差別就是 javaType換成   column       resultMap換成select   實體類的屬性名不一樣
column 的值就是主表查詢出來的id給子查詢
select 的值 就是子值查詢的id名稱
    <!--    一對多-->
    <resultMap id="prodMap" type="product_type">
        <id property="id" column="id"/>
        <collection property="productList" column="id" select="show1Select">
            <!-- 子查詢 如果實體類的屬性和 資料庫字段一緻就不用手動映射
                select的方法如果跨xml檔案的話,需要追加方法xml檔案的指令空間比如: 
                com.example.applicationserve1.dao.UserDao.show1Select
			-->
        </collection>
    </resultMap>
        
   <select id="show" resultMap="prodMap" parameterType="int" >
      select * from product_type where id=#{id}
   </select>
   <select id="show1Select" resultType="product" parameterType="int">
    select * from product where type_id=#{id}
  </select>
        
           

多對多 就是一對多的更新版 需要至少3個表 原理一樣

表1 對應 表2 多條資料或一條資料

表2對應表3 多條資料或一條資料

表三對應表2多條資料或一條資料

就好像把他們都關聯起來了 核心就是表2

項目中在使用association一對多關系時需要對關系中結果集進行多條件篩選時候,查詢參數傳遞成為問題。 (用的少)

我們可以使用下面這種文法:

column=“{prop1=col1,prop2=col2}” 這樣的文法,設定多個列名傳入到嵌套查詢語句。這就會把prop1和prop2設定到目标嵌套選擇語句的參數對象中

<collection 
property="quotechatTrackOfferAdviceDo" 
javaType="java.util.ArrayList" 
ofType="com.chinare.brp.biz.biz.domain.QuoteChatTrackDo"
column="{quoteId=quote_id}"
select="com.chinare.brp.biz.biz.dao.QuotechatTrackDao.getQuote1dofferAdviceAl1"/>
           

動态sql

使用動态sql完成多條件查詢增删改等邏輯實作

用于實作動态sql的元素主要有

if

trim

where

set

choose(when,otherwise)

foreach

在這些條件中的變量, 不需能使用#{} 或者${} 而是直接寫名稱就行

如果是實體類那麼就寫屬性名 沒有實體類就方法參數名或者@Param注解的别名…

為什麼要用到 動态 sql 因為 當使用者傳入的參數 為空 或者不符合 的時候 怎麼辦 難道就什麼都不顯示 這肯定是不行的

是以就要用 多套 sql 方案 當第一條不滿足 執行第二條 等等 直到滿足

我們在使用模糊查詢時候需要用到 mysql的concat(str1,str2,…) 字元串函數進拼接

%

而不能直接使用+号進行拼接否則報錯

if

<!-- if -->
<select id="getUserIF" resultType="User">
    select * from xingxi where 1=1
    <if test="user !=null and user !=''">
       and  user LIKE CONCAT(#{user},'%')
    </if>
    <if test="user!=null and user !='' and name !=null and name !=''">
        and name=#{name}
    </if>
</select>

解析 第一個if 當user 不等于空 的時候  執行 
	第二個if 當user 和name 都不為空 執行  
	如果都不滿足那麼就查詢全部


           

where

<!--使用 where 來包裝if子元素 -->

<select id="getUserIF" resultType="User">
    select * from xingxi
    <where>
        <if test="user !=null and user!='' ">
            user LIKE CONCAT(#{user},'%')
        </if>
        <if test="name !=null  and name!='' ">
            and name=#{name}
        </if>
    </where>

</select>

隻要有一個條件執行 就會自動補上 where  
而且會自動适配 進行去掉 and或or(生成可執行sql)

           

trim-if

<!-- trim-if元素 -->
更靈活 的去除 多餘的 關鍵字  where更新版 因為where隻能處理 and 和or
屬性
prefix	(字首 當trim中隻要有一條if 成功 就會 補上這個字首 中 聲明的 語句  ( trim 下 語句 最前面))
suffix (字尾 當trim中隻要有一條if 成功 就會 補上這個字尾中 聲明的 語句 (補到trim 下 語句最後面))

prefixOverrides(去除指定 trim 下 sql語句 首部  的語句 比如 and  or )
suffixOverrides(去除指定 sql語句 尾部  的語句 比如 and  or) 
<!--動态sql  trim  前-->
<select id="getUserIF" resultType="User">
    select * from xingxi
    <trim prefix="where" prefixOverrides="and|or">
        <if test="user !=null and user.trim().length()!=0">
            user LIKE CONCAT(#{user},'%')
        </if>
        <if test="name !=null  and  name.trim().length()!=0">
            and name=#{name}
        </if>
    </trim>

</select>

第一條if滿足添加where   如果有and或or 就去掉
如果第一條不滿足 第二條滿足就 添加where   如果有and或or 就去掉
如果都滿足  添加where 去掉首部的 and或or(形成可執行sql)

           

set-if

set-if更新操作 (指定更新值不為空的字段)
在不使用 動态更新 的時候  如果 某個 更新時候 參數 為null  或者” ”  有可能會錯誤  并且覆寫掉原來的值,但是在實際的更新 中 有的時候 就隻需要更新 幾個字段 不需要其他那麼多  在不改變sql 語句的前期下怎麼辦
正确的辦法 當某個參數為空  則不需要更新,保留原來的資料
接口:public int modify_UP(User user);

<update id="modify_UP" parameterType="User">
update xingxi
    <set>
        <if test="user !=null and user!=''">
            user=#{user},
        </if>
        <if test="pass !=null and pass!=''">
            pass=#{pass},
        </if>
        <if test="name !=null and name!=''">
            name=#{name},
        </if>
    </set>
 where user=#{user_up}
</update>
解析
	将if條件成立的 語句 補到 修改語句的後面 自動在前面添加set 
	而set 有自動抹除 最後 的逗号 多以不用擔心加多逗号   (最後一個逗号 加不加都可以)

           

trim -if

使用trim -if 
接口:public int modify_UP(User user);  
    <!--動态sql 修改trim字尾 -->
	<update id="modify_UP" parameterType="User">
    update xingxi
<trim prefix="set" suffixOverrides="," suffix="where user=#{user_up}">
    <if test="user !=null and user!=''">
        user=#{user},
	</if>
    <if test="pass !=null and pass!=''">
        pass=#{pass},</if>
    <if test="name !=null and name!=''">
        name=#{name},
	</if>
</trim>
</update>
prefix="set" 當 trim下面if 隻要有一條滿足 就會 補充set  
suffixOverrides=","  清除trim 内 sql語句 最後面的逗号  (有了就清除沒有就不清除)
suffix="where user=#{user_up}" 在trim 内sql語句 最後補上  此屬性聲明的值


           

foreach

疊代一個集合 ,通常用in條件

item(集合時每一個元素疊代時的 别名)

index(指定一個名字 表示每次疊代的位置(可以省略))

collection:必須指定(指定周遊類型) (切記都是是小寫 别寫成大寫的了不然報錯)

list 集合

array 數組

map-key map

open (以什麼為開始 一般以括号開始)

separator (每次疊代之間以什麼 間隔)

close (以什麼結束 )

以array形式

接口:public List<User> getUser_foreach_in(Integer[] forid);
假設我傳進來:Integer[] forid={2,3};
<!-- foreach -in   array數組操作-->
    <select id="getUser_foreach_in"  resultType="User">
        select * from xingxi  where id in
        <foreach collection="array" item="id" open ="(" separator="," close=")">
        #{id}
        </foreach>
    </select>
           

解析

collection=“array” 指定傳進來的是數組

item=“id” 周遊疊代值

open ="(" 以 ( 開頭

separator="," 每次周遊 以 , 間隔

close=")" 以 ) 結尾

會自動适配 的如果是最後一個了 就不會在添加逗号了

最後就形成了一個完整的 sql in語句

select * from xingxi where id in(2,3)

以list形式

List<Integer> list= new ArrayList<>();
list.add(2);
list.add(3);
接口:public List<User> getUser_foreach_in_list(List<Integer> forid);
    
    
    <!-- foreach -in   List集合操作-->
<select id="getUser_foreach_in_list" resultType="User">
    select * from xingxi  where id in
    <foreach collection="list" item="id" open ="(" separator="," close=")">
        #{id}
    </foreach>
</select>
           

和array 一樣 也就把類型變了

以map-key形式

将數組 等放進 map中 利用key來擷取或者周遊

當 一個查詢元素 需要多個參數 也就是 foreach裡面需要 外面也需要 或者 多個list 和多個array的情況下

可以将他們 封裝 成一個map 以key 來調用對應的值

Map<String,Object> map=new HashMap<>();
List<Integer> list= new ArrayList<>();
list.add(2);
list.add(3);
map.put("id",list);
map.put("pass","123");
接口:public List<User> getUser_foreach_in_map(Map<String,Object> forid);
    
 <!-- foreach -in   Map集合操作-->
<select id="getUser_foreach_in_map" resultType="User">
    select * from xingxi  where id in
    <foreach collection="id" item="id_map" open ="(" separator="," close=")">
        #{id_map}
    </foreach>
    and  pass=#{pass}
</select>
這裡的  collection調用的是 map id(key值)裡的 list集合   因為 foreach隻能周遊集合  還有就是 因為傳入的是 map  整個 标簽内都可以通過key來 調用 對應的值 比如#{pass}
   
           

choose(when,otherwise)

相當于java中switch --case case default 和 if if if else語句

當when有條件滿足的時就執行滿足的when 然後跳出choose 如果都不滿足就執行otherwise

然後在就跳出choose 當然 otherwise 也可以不寫

String user="";
String pass="";
String name="阿薩達";

接口
	public List<User> getUserList_choose(@Param("user") String user ,@Param("pass") String pass,@Param("name")String name);
        
    
<select id="getUserList_choose" resultType="User">
     select * from xingxi  where 1=1
     <choose>
         <when test="user !=null and user.trim().length()!=0">
             and user =#{user}
         </when>
         <when test="pass !=null and pass.trim().length()!=0">
             and pass =#{pass}
         </when>
         <otherwise>
             and name=#{name}
         </otherwise>

     </choose>

</select>
    
小提示 有細心地可以看到 我在where後面 加了一個1=1 是幹什麼的   如果不加1=1  那就必須要進行 去除 and  或者 or  否則就 報錯 了      select * from xingxi where  and name=?  (肯定報錯)   是以你懂的 
當然是用trim也是可以的 但是 比較麻煩  還是使用 1=1比較簡單

           

分頁查詢

步驟一 :  先計算一共要分多少頁
	步驟二:   将資料進行排序  一般都是按照 降序
	步驟三:  指定顯示每頁的資料數量 (limit 頁碼-1*頁面容量,頁面容量)   計算起始位置從1開始 不要從0開始 因為 0-1=-1就沒法計算了.
而實作分頁查詢 不是 在dao層實作  而是 在 service層來進行處理的  通過使用者點選的頁數計算後 将起始位 添加到sql語句中  傳回給前端對應頁數的資料

        計算總數量
接口public int count_fenye();
Mapper

<select id="count_fenye" resultType="int">
    select count(*) from result
</select>
        

    
      分頁
接口
public List<User> getUserList_fenye(@Param("qishi")Integer qishi,@Param("size") Integer size);

<select id="getUserList_fenye" resultType="User">
    select * from result 
    order by  StudentNo desc 
    LIMIT #{qishi} ,#{size}
</select>

           

注釋

标簽外使用

标簽内使用 –

<!--查詢全部資料條數-->
    <select id="userCount" resultType="Integer">
     -- 這是sql注釋
        SELECT COUNT(*) FROM t_user
    </select>

           

調用存儲過程

MyBatis 可以一次執行多條SQL語句,但 沒法一次傳回多個結果集。

<select id="test" parameterType="Map" resultType="Map">
    select * from tableA;
    updata .....
    delete.....
    insert......
     <!--我想說的是更新、删除、插入等可以任意組合  注意沒有查詢-->
</select>
           

如果存儲過程 傳回多個解決集那麼 如果表是一樣的話,

使用 UNION ALL 如果需要去重,合并的話那麼UNION就行

如果表不一樣的話隻能在寫一份配置了…經過各種實作mybaitis是無法實作多結果集的網上有人說

使用List<List<?>> 本人以測試過無效,也有人說使用映射,本人以測試過無效

1、mapper.xml檔案中配置相關的sql語句。

<select id="callTest" statementType="CALLABLE" useCache="false" >
    {
        call hasResource(
                #{param1,mode=IN},
                #{param2,mode=IN},
                #{param3,mode=OUT,jdbcType=INTEGER}
            )
    }
</select>
           

注意:parameterMap已被舍棄,請直接在sql語句中定義傳參類型。

在存儲過程中使用參數時,必須指定參數的mode(模式),可選的值為IN、OUT、INOUT。入參使用IN,出參使用OUT,輸入輸出參數用INOUT,OUT模式下必須指定jdbcType,這是因為在IN模式下,Mybatis提供了預設的jdbcType

常用的jdbcType/javaType:

  1. VARCHAR =String
  2. DECIMAL=java.math.BigDecimal
  3. BOOLEAN =boolean
  4. INTEGER=int
  5. BIGINT=long
  6. DOUBLE=double
  7. DATE=java.sql.Date

存儲過程方式不支援mybatis的二級緩存 需要關閉

useCache="false"

statementType=”CALLABLE” 必須為CALLABLE,告訴MyBatis去執行存儲過程, 否則會報錯

Exception in thread “main” org.apache.ibatis.exceptions.PersistenceException

當然不止

<selec>

能調用

<delect>

,

<update>

,

<insert>

這些都能使用,隻是含義不一樣而已 ,用法一緻

<!-- 删除使用者 -->
	<delete id="deleteUser" parameterType="Integer" useCache="false"  statementType="CALLABLE">
		{call deleteUser(#{id,mode=IN})}
	</delete>
           
<!-- 更新使用者 -->
	<update id="updateUser" parameterType="user" useCache="false" statementType="CALLABLE">
		{call updateUser(#{id,mode=IN},#{name,mode=IN},#{sex,mode=IN},#{age,mode=IN})}
	</update>
           
<!-- 根據id查詢使用者 -->
	<select id="getUserById" parameterType="Integer" useCache="false"  resultType="user" statementType="CALLABLE">
		{call getUserById(#{id,mode=IN})}
	</select>
           

2、定義mapper接口中的方法

注意:如果存儲過程中有OUT參數,調用時的傳參隻能是Map類型,調用結束後從Map中根據OUT參數的名稱擷取傳回的資料。如果沒有OUT參數,可以使用@Param方式定義接口中的傳參。

如果傳回是類似SELECT 查詢的結果集那麼傳回類型就要換成,

  1. Object 一條資料時候
  2. List<Object> 單結果集的時候 (多條資料)

如果單純隻是用存儲過程增删改,沒有傳回結果集 那麼 void 就行

調用自定義函數

和調用SELECT一樣但是因為函數 就隻能傳回一個值:

<select id="getUserById" parameterType="Integer"  resultType="String" >
		SELECT getUserCount(#{userId,mode=IN})
	</select>
           

或者

<!-- 存儲函數:根據使用者編号,擷取使用者名稱 -->
<select id="func_get_user_name" statementType="CALLABLE" parameterType="hashMap" >
    {
    #{userName,mode=OUT,jdbcType=VARCHAR} = 
    CALL func_get_user_name(#{userId,mode=IN,jdbcType=INTEGER})
    }
</select>
           

上面這個函數是根據userId擷取姓名 , 然後将結果存入userName中

這種方式需要接口參數是Map,然後函數自動将結果傳回到Map中

Map userMap = new HashMap();
    userMap.put("userName","");
    userMap.put("userId",8);
    userservice.funcUserName(userMap)     
    System.out.println("使用者名稱:" + userMap.get("userName"));      
           

出現的問題和解決辦法

invalid comparison: java.util.Date and java.lang.String

出現上面的錯誤是在mapper.xml中拿時間類型進行非空判斷了

比如: 實體類或者方法的參數類型是: private Date theDate;

然後我們在Mapper.xml

解決辦法:

把上代碼改為下面代碼就能解決

sql injection violation, dbType multi-statement not allow

在項目開發的時遇到同時執行多條删除或者更新語句,将語句放到mysql指令行來執行是沒有問題的,可到了mybatis就報錯,為啥呢?

<update id="updateId">
   delete from user_1 where time<#{time};
   delete from user_2 where time<#{time};
</update>
           

當然了,這段sql語句看似沒有啥錯誤,但如果沒有開啟批量處理,就會報錯。

其實隻要在連接配接的URL後面加上&allowMultiQueries=true就可以了

如果使用的使用阿裡巴巴的 Druid 連接配接池那麼還需要配置

@Bean
    public WallFilter wallFilter(){
        WallFilter wallFilter=new WallFilter();//配置一個監控的filter
        wallFilter.setConfig(wallConfig());//導入我們的配置
        return wallFilter;
    }
    @Bean
    public WallConfig wallConfig(){
        WallConfig config =new WallConfig();
        config.setMultiStatementAllow(true);//允許一次執行多條語句
        config.setNoneBaseStatementAllow(true);//允許非基本語句的其他語句
        return config;
    }
           

一般在查詢裡用不到,同時執行多個sql的情況 ,一般都是在增删改查中使用

<updata id="test" parameterType="Map" >
    updata .....
    delete.....
     delete.....
    insert......
     <!--我想說的是更新、删除、插入等可以任意組合  注意沒有查詢-->
</updata>
           

存儲過程

<updata id="test" parameterType="Map" useCache="false" tatementType="CALLABLE" >
    updata .....
    delete.....
     delete.....
    insert......
     <!--我想說的是更新、删除、插入等可以任意組合  注意沒有查詢-->
</updata>
           

mybatis僅傳入一個String參數時候報錯

<select id="getOrderListSQL" resultType="order" parameterType="String">
   SELECT * FROM table name= #{name}
</select>
           

There is no getter for property named 'type ’ in ‘class java.lang.String’

解決辦法: 在接口參數裡加上mybatis中的@param注解

如果不想使用(@Param 那麼在xml中直接使用#{value} 注意: value是固定寫法

點贊 -收藏加 -關注 便于以後複習和收到最新内容 有其他問題在評論區讨論-或者私信我-收到會在第一時間回複 感謝,配合,希望我的努力對你有幫助^_^