1. 程式人生 > >mybatis的基本語句的應用

mybatis的基本語句的應用

lis 默認 map query resultset 關系 serve 形式 tag

大家好今晚整理有關mybatis的添加刪除修改更新的操作

一、select

技術分享圖片
<!-- 查詢學生,根據id -->  
<select id="getStudent" parameterType="String" resultMap="studentResultMap">  
    SELECT ST.STUDENT_ID,  
               ST.STUDENT_NAME,  
               ST.STUDENT_SEX,  
               ST.STUDENT_BIRTHDAY,  
               ST.CLASS_ID  
          FROM STUDENT_TBL ST  
         WHERE ST.STUDENT_ID = #{studentID}  
</select>  
技術分享圖片

這條語句就叫做‘getStudent,有一個String參數,並返回一個StudentEntity類型的對象。
註意參數的標識是:#{studentID}。

select 語句屬性配置細節:

屬性描述取值默認
id 在這個模式下唯一的標識符,可被其它語句引用
parameterType 傳給此語句的參數的完整類名或別名
resultType 語句返回值類型的整類名或別名。註意,如果是集合,那麽這裏填寫的是集合的項的整類名或別名,而不是集合本身的類名。(resultType 與resultMap 不能並用)
resultMap 引用的外部resultMap 名。結果集映射是MyBatis 中最強大的特性。許多復雜的映射都可以輕松解決。(resultType 與resultMap 不能並用)
flushCache 如果設為true,則會在每次語句調用的時候就會清空緩存。select 語句默認設為false true/false false
useCache 如果設為true,則語句的結果集將被緩存。select 語句默認設為false true/false false
timeout 設置驅動器在拋出異常前等待回應的最長時間,默認為不設值,由驅動器自己決定 正整數 未設置
fetchSize 設置一個值後,驅動器會在結果集數目達到此數值後,激發返回,默認為不設值,由驅動器自己決定 正整數 驅動器決定
statementType statement,preparedstatement,callablestatement。預準備語句、可調用語句 STATEMENT、PREPARED、CALLABLE PREPARED
resultSetType forward_only、scroll_sensitive、scroll_insensitive 只轉發,滾動敏感,不區分大小寫的滾動 FORWARD_ONLY、SCROLL_SENSITIVE、SCROLL_INSENSITIVE 驅動器決定

二、insert

一個簡單的insert語句:

技術分享圖片
<!-- 插入學生 -->  
<insert id="insertStudent" parameterType="StudentEntity">  
        INSERT INTO STUDENT_TBL (STUDENT_ID,  
                                          STUDENT_NAME,  
                                          STUDENT_SEX,  
                                          STUDENT_BIRTHDAY,  
                                          CLASS_ID)  
              VALUES   (#{studentID},  
                          #{studentName},  
                          #{studentSex},  
                          #{studentBirthday},  
                          #{classEntity.classID})  
</insert>  
技術分享圖片

insert可以使用數據庫支持的自動生成主鍵策略,設置useGeneratedKeys=”true”,然後把keyProperty 設成對應的列,就搞定了。比如說上面的StudentEntity 使用auto-generated 為id 列生成主鍵.

<insert id="insertStudent" parameterType="StudentEntity" useGeneratedKeys="true" keyProperty="studentID">

推薦使用這種用法。

另外,還可以使用selectKey元素。下面例子,使用MySQL數據庫nextval(‘student’)為自定義函數,用來生成一個key。

技術分享圖片
<!-- 插入學生 自動主鍵-->  
<insert id="insertStudentAutoKey" parameterType="StudentEntity">  
    <selectKey keyProperty="studentID" resultType="String" order="BEFORE">  
            select nextval(‘student‘)  
    </selectKey>  
        INSERT INTO STUDENT_TBL (STUDENT_ID,  
                                 STUDENT_NAME,  
                                 STUDENT_SEX,  
                                 STUDENT_BIRTHDAY,  
                                 CLASS_ID)  
              VALUES   (#{studentID},  
                        #{studentName},  
                        #{studentSex},  
                        #{studentBirthday},  
                        #{classEntity.classID})      
</insert>  
技術分享圖片

insert語句屬性配置細節:

屬性描述取值默認
id 在這個模式下唯一的標識符,可被其它語句引用
parameterType 傳給此語句的參數的完整類名或別名
flushCache 如果設為true,則會在每次語句調用的時候就會清空緩存。select 語句默認設為false true/false false
useCache 如果設為true,則語句的結果集將被緩存。select 語句默認設為false true/false false
timeout 設置驅動器在拋出異常前等待回應的最長時間,默認為不設值,由驅動器自己決定 正整數 未設置
fetchSize 設置一個值後,驅動器會在結果集數目達到此數值後,激發返回,默認為不設值,由驅動器自己決定 正整數 驅動器決定
statementType statement、preparedstatement、callablestatement。預準備語句、可調用語句 STATEMENT、PREPARED、CALLABLE PREPARED
useGeneratedKeys 告訴MyBatis 使用JDBC 的getGeneratedKeys 方法來獲取數據庫自己生成的主鍵(MySQL、SQLSERVER 等關系型數據庫會有自動生成的字段)。默認:false true/false false
keyProperty 標識一個將要被MyBatis設置進getGeneratedKeys的key 所返回的值,或者為insert 語句使用一個selectKey子元素。

selectKey語句屬性配置細節:

屬性描述取值
keyProperty selectKey 語句生成結果需要設置的屬性。
resultType 生成結果類型,MyBatis 允許使用基本的數據類型,包括String 、int類型。
order 可以設成BEFORE 或者AFTER,如果設為BEFORE,那它會先選擇主鍵,然後設置keyProperty,再執行insert語句;如果設為AFTER,它就先運行insert 語句再運行selectKey 語句,通常是insert 語句中內部調用數據庫(像Oracle)內嵌的序列機制。 BEFORE/AFTER
statementType 像上面的那樣, MyBatis 支持STATEMENT,PREPARED和CALLABLE 的語句形式, 對應Statement ,PreparedStatement 和CallableStatement 響應 STATEMENT、PREPARED、CALLABLE

批量插入

方法一:

<insert id="add" parameterType="EStudent">
  <foreach collection="list" item="item" index="index" separator=";">
    INSERT INTO TStudent(name,age) VALUES(#{item.name}, #{item.age})
  </foreach>
</insert>

上述方式相當語句逐條INSERT語句執行,將出現如下問題:
1. mapper接口的add方法返回值將是最一條INSERT語句的操作成功的記錄數目(就是0或1),而不是所有INSERT語句的操作成功的總記錄數目
2. 當其中一條不成功時,不會進行整體回滾。

方法二:

技術分享圖片
<insert id="insertStudentAutoKey" parameterType="java.util.List">
    INSERT INTO STUDENT_TBL (STUDENT_NAME,  
                                 STUDENT_SEX,  
                                 STUDENT_BIRTHDAY,  
                                 CLASS_ID)  
                              VALUES   
  <foreach collection="list" item="item" index="index" separator=",">
      ( #{item.studentName},#{item.studentSex},#{item.studentBirthday},#{item.classEntity.classID})
  </foreach>
  </insert>
技術分享圖片

三、update

一個簡單的update:

技術分享圖片
<!-- 更新學生信息 -->  
<update id="updateStudent" parameterType="StudentEntity">  
        UPDATE STUDENT_TBL  
            SET STUDENT_TBL.STUDENT_NAME = #{studentName},   
                STUDENT_TBL.STUDENT_SEX = #{studentSex},  
                STUDENT_TBL.STUDENT_BIRTHDAY = #{studentBirthday},  
                STUDENT_TBL.CLASS_ID = #{classEntity.classID}  
         WHERE STUDENT_TBL.STUDENT_ID = #{studentID};     
</update>
技術分享圖片

update語句屬性配置細節:

屬性描述取值默認
id 在這個模式下唯一的標識符,可被其它語句引用
parameterType 傳給此語句的參數的完整類名或別名
flushCache 如果設為true,則會在每次語句調用的時候就會清空緩存。select 語句默認設為false true/false false
useCache 如果設為true,則語句的結果集將被緩存。select 語句默認設為false true/false false
timeout 設置驅動器在拋出異常前等待回應的最長時間,默認為不設值,由驅動器自己決定 正整數 未設置
fetchSize 設置一個值後,驅動器會在結果集數目達到此數值後,激發返回,默認為不設值,由驅動器自己決定 正整數 驅動器決定
statementType statement、preparedstatement、callablestatement。預準備語句、可調用語句 STATEMENT、PREPARED、CALLABLE PREPARED

批量更新

情景一:更新多條記錄為多個字段為不同的值
方法一:

技術分享圖片
<update id="updateBatch"  parameterType="java.util.List">  
    <foreach collection="list" item="item" index="index" open="" close="" separator=";">
        update course
        <set>
            name=${item.name}
        </set>
        where id = ${item.id}
    </foreach>      
</update>
技術分享圖片

比較普通的寫法,是通過循環,依次執行update語句。

方法二:

技術分享圖片
UPDATE TStudent SET Name = R.name, Age = R.age
from (
  SELECT ‘Mary‘ as name, 12 as age, 42 as id
  union all
  select ‘John‘ as name , 16 as age, 43 as id
) as r 
where ID = R.id
技術分享圖片

情景二:更新多條記錄的同一個字段為同一個值

<update id="updateOrders" parameterType="java.util.List">
     update orders set state = ‘0‘ where no in
     <foreach collection="list" item="id" open="(" separator="," close=")">
   #{id}
     </foreach>
 </update>

四、delete

一個簡單的delete:

<!-- 刪除學生 -->  
<delete id="deleteStudent" parameterType="StudentEntity">  
        DELETE FROM STUDENT_TBL WHERE STUDENT_ID = #{studentID}  
</delete>  

delete語句屬性配置細節同update

批量刪除:

技術分享圖片
<!-- 通過主鍵集合批量刪除記錄 -->

<delete id="batchRemoveUserByPks" parameterType="java.util.List">

  DELETE FROM LD_USER WHERE ID in 

  <foreach item="item" index="index" collection="list" open="(" separator="," close=")">

    #{item}

  </foreach>

</delete>
技術分享圖片

五、sql元素

Sql元素用來定義一個可以復用的SQL 語句段,供其它語句調用。比如:

技術分享圖片
<!-- 復用sql語句  查詢student表所有字段 -->  
<sql id="selectStudentAll">  
        SELECT ST.STUDENT_ID,  
                   ST.STUDENT_NAME,  
                   ST.STUDENT_SEX,  
                   ST.STUDENT_BIRTHDAY,  
                   ST.CLASS_ID  
              FROM STUDENT_TBL ST  
</sql>  
技術分享圖片

這樣,在select的語句中就可以直接引用使用了,將上面select語句改成:

<!-- 查詢學生,根據id -->  
<select id="getStudent" parameterType="String" resultMap="studentResultMap">  
    <include refid="selectStudentAll"/>  
            WHERE ST.STUDENT_ID = #{studentID}   
</select>  

六、parameters

上面很多地方已經用到了參數,比如查詢、修改、刪除的條件,插入,修改的數據等,MyBatis可以使用Java的基本數據類型和Java的復雜數據類型。如:基本數據類型,String,int,date等。

但是使用基本數據類型,只能提供一個參數,所以需要使用Java實體類,或Map類型做參數類型。通過#{}可以直接得到其屬性。

1、基本類型參數

根據入學時間,檢索學生列表:

<!-- 查詢學生list,根據入學時間  -->  
<select id="getStudentListByDate"  parameterType="Date" resultMap="studentResultMap">  
    SELECT *  
      FROM STUDENT_TBL ST LEFT JOIN CLASS_TBL CT ON ST.CLASS_ID = CT.CLASS_ID  
     WHERE CT.CLASS_YEAR = #{classYear};      
</select>  
List<StudentEntity> studentList = studentMapper.getStudentListByClassYear(StringUtil.parse("2007-9-1"));  
for (StudentEntity entityTemp : studentList) {  
    System.out.println(entityTemp.toString());  
} 

2、Java實體類型參數

根據姓名和性別,檢索學生列表。使用實體類做參數:

<!-- 查詢學生list,like姓名、=性別,參數entity類型 -->  
<select id="getStudentListWhereEntity" parameterType="StudentEntity" resultMap="studentResultMap">  
    SELECT * from STUDENT_TBL ST  
        WHERE ST.STUDENT_NAME LIKE CONCAT(CONCAT(‘%‘, #{studentName}),‘%‘)  
          AND ST.STUDENT_SEX = #{studentSex}  
</select>  
技術分享圖片
StudentEntity entity = new StudentEntity();  
entity.setStudentName("李");  
entity.setStudentSex("男");  
List<StudentEntity> studentList = studentMapper.getStudentListWhereEntity(entity);  
for (StudentEntity entityTemp : studentList) {  
    System.out.println(entityTemp.toString());  
}  
技術分享圖片

3、Map參數

根據姓名和性別,檢索學生列表。使用Map做參數:

<!-- 查詢學生list,=性別,參數map類型 -->  
<select id="getStudentListWhereMap" parameterType="Map" resultMap="studentResultMap">  
    SELECT * from STUDENT_TBL ST  
     WHERE ST.STUDENT_SEX = #{sex}  
          AND ST.STUDENT_SEX = #{sex}  
</select>  
技術分享圖片
Map<String, String> map = new HashMap<String, String>();  
map.put("sex", "女");  
map.put("name", "雪");  
List<StudentEntity> studentList = studentMapper.getStudentListWhereMap(map);
for (StudentEntity entityTemp : studentList) {  
    System.out.println(entityTemp.toString());  
}  
技術分享圖片

4、多參數的實現

如果想傳入多個參數,則需要在接口的參數上添加@Param註解。給出一個實例:
接口寫法:

public List<StudentEntity> getStudentListWhereParam(@Param(value = "name") String name, @Param(value = "sex") String sex, @Param(value = "birthday") Date birthdar, @Param(value = "classEntity") ClassEntity classEntity);  

sql寫法:

技術分享圖片
<!-- 查詢學生list,like姓名、=性別、=生日、=班級,多參數方式 -->  
<select id="getStudentListWhereParam" resultMap="studentResultMap">  
    SELECT * from STUDENT_TBL ST  
    <where>  
        <if test="name!=null and name!=‘‘ ">  
            ST.STUDENT_NAME LIKE CONCAT(CONCAT(‘%‘, #{name}),‘%‘)  
        </if>  
        <if test="sex!= null and sex!= ‘‘ ">  
            AND ST.STUDENT_SEX = #{sex}  
        </if>  
        <if test="birthday!=null">  
            AND ST.STUDENT_BIRTHDAY = #{birthday}  
        </if>  
        <if test="classEntity!=null and classEntity.classID !=null and classEntity.classID!=‘‘ ">  
            AND ST.CLASS_ID = #{classEntity.classID}  
        </if>  
    </where>  
</select>  
技術分享圖片

進行查詢:

List<StudentEntity> studentList = studentMapper.getStudentListWhereParam("","",StringUtil.parse("1985-05-28"), classMapper.getClassByID("20000002"));  
for (StudentEntity entityTemp : studentList) {  
    System.out.println(entityTemp.toString());  
}  

七、#{}與${}的區別

默認情況下,使用#{}語法,MyBatis會產生PreparedStatement語句中,並且安全的設置PreparedStatement參數,這個過程中MyBatis會進行必要的安全檢查和轉義。
示例1:

執行SQL:Select * from emp where name = #{employeeName}
參數:employeeName=>Smith
解析後執行的SQL:Select * from emp where name = ?

執行SQL:Select * from emp where name = ${employeeName}
參數:employeeName傳入值為:Smith
解析後執行的SQL:Select * from emp where name =Smith

說明:
1. #將傳入的數據都當成一個字符串,會對自動傳入的數據加一個雙引號。如:order by #{user_id},如果傳入的值是111,那麽解析成sql時的值為order by “111”, 如果傳入的值是id,則解析成的sql為order by “id”.

2. $將傳入的數據直接顯示生成在sql中。如:order by ${user_id},如果傳入的值是111,那麽解析成sql時的值為order by 111, 如果傳入的值是id,則解析成的sql為order by id.

綜上所述,${}方式會引發SQL註入的問題、同時也會影響SQL語句的預編譯,所以從安全性和性能的角度出發,能使用#{}的情況下就不要使用${}。

${}在什麽情況下使用呢?

有時候可能需要直接插入一個不做任何修改的字符串到SQL語句中。這時候應該使用${}語法。

比如,動態SQL中的字段名,如:ORDER BY ${columnName}

<select id="queryMetaList" resultType="Map" statementType="STATEMENT">
    Select * from emp where name = ${employeeName} ORDER BY ${columnName}
</select> 

由於${}僅僅是簡單的取值,所以以前sql註入的方法適用此處,如果我們order by語句後用了${},那麽不做任何處理的時候是存在sql註入危險的。

2019-03-3022:43:43

mybatis的基本語句的應用