Mybatis基礎知識

MyBatis 是支持定製化 SQL、存儲過程以及高級映射的優秀的持久層框架,其主要就完成2件事情:

    1. 封裝JDBC操作
    1. 利用反射打通Java類與SQL語句之間的相互轉換

MyBatis的主要設計目的就是讓我們對執行SQL語句時對輸入輸出的數據管理更加方便,所以方便地寫出SQL和方便地獲取SQL的執行結果纔是MyBatis的核心競爭力。

接口映射

在使用MyBatis的時候,都用的是Dao接口和XML文件裏的SQL一一對應來進行使用的。那你是否思考過二者是如何建立關係的?

MyBatis會先解析這些XML文件,通過XML文件裏面的命名空間(namespace)跟DAO建立關係;然後XML中的每段SQL會有一個id跟DAO中的接口進行關聯。

Dao接口裏的方法,是不能重載的,因爲是全限名+方法名的保存和尋找策略

通常一個Xml映射文件,都會寫一個Dao接口與之對應。Dao接口,就是人們常說的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法內的參數,就是傳遞給sql的參數。Mapper接口是沒有實現類的,當調用接口方法時,接口全限名+方法名拼接字符串作爲key值,可唯一定位一個MappedStatement。

如果配置了namespace,那麼id是可以重複的,因爲我們的Statement實際上就是namespace+id

舉例:com.mybatis3.mappers.StudentDao.findStudentById,可以唯一找到namespace爲com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。在Mybatis中,每一個<select>、<insert>、<update>、<delete>標籤,都會被解析爲一個MappedStatement對象。

#{}和${}的區別是什麼?

  • #{}解析傳遞進來的參數數據
  • ${}對傳遞進來的參數原樣拼接在SQL中
  • Mybatis 在處理#{}時,會將 sql 中的#{}替換爲?號,調用 PreparedStatement 的 set 方法來賦值;
    Mybatis 在處理 美元符號{} 時,就是把${}替換成變量的值
  • #{}是預編譯處理,${}是字符串替換
  • 使用#{}可以有效的防止SQL注入,提高系統安全性。
select * from ${tableName} where name = #{name}
  在這個例子中,如果表名爲

user; delete user; –

則動態解析之後 sql 如下:

select * from user; delete user; – where name = ?;
  --之後的語句被註釋掉,而原本查詢用戶的語句變成了查詢所有用戶信息+刪除用戶表的語句,會對數據庫造成重大損傷,極大可能導致服務器宕機。


    '#‘相當於對數據 加上 雙引號,’$'相當於直接顯示數據

    '#'將傳入的數據都當成一個字符串,會對自動傳入的數據加一個雙引號。

    '$'將傳入的數據直接顯示生成在sql中。
  • #{} 用於CRUD語句
    ${} 則用於模糊查詢(記得加%%哦),}一般用在order by, limit, group by等場所。

如何獲取自動生成的(主)鍵值?

如果我們一般插入數據的話,如果我們想要知道剛剛插入的數據的主鍵是多少(一般這個主鍵是自增ID),一般情況下我們可能在以某個唯一字段與數據庫進行一次查詢交互,獲取到自增id,但是這樣相對比較麻煩,我們可以通過對mybatis進行配置。

    <insert id="insert" parameterType="com.qufenqi.pay.settlement.dao.po.SettleBasicData" useGeneratedKeys="true"
            keyProperty="id" keyColumn="id">
    insert into sett_basic_data (id, biz_order_no, biz_type, 
      fund_type, trade_mode, merchant_id, merchant_name, 
      create_time, update_time)
    values (#{id,jdbcType=BIGINT}, #{bizOrderNo,jdbcType=VARCHAR}, #{bizType,jdbcType=VARCHAR}, 
      #{fundType,jdbcType=VARCHAR}, #{tradeMode,jdbcType=VARCHAR}, #{merchantId,jdbcType=VARCHAR}, #{merchantName,jdbcType=VARCHAR},
      #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP})
  </insert>

在上述方法中添加useGeneratedKeys="true" keyProperty="id" keyColumn="id"
settleBasicDataMapper.insert(settleBasicData); settleBasicData.getId();
代碼親測有效

在mapper中如何傳遞多個參數?

  • 使用佔位符的思想

    其中,#{0}代表接收的是dao層中的第一個參數,#{1}代表dao層中第二參數,更多參數一致往後加即可。

  • 採用Map傳多參數 parameterType=“hashmap”

  • Dao層的函數方法,和佔位符有些類似,目前單個參數用的主流方法(使用@Param註解)

  • 通過註解的方法查詢(配合@Param註解)

  • 採用javaBean(一般應用於更新和查詢情況)

    這種方法很直觀,但需要建一個實體類,擴展不容易,需要加屬性,看情況使用。

附帶一個批量更新數據庫的sql
對SettleBasicData集合中的每條數據進行更新

int updateBatch(@Param(value = "list") List<SettleBasicData> list);

    <update id="updateBatch" parameterType="java.util.List">
        <foreach collection="list" item="item" index="index" open="" close="" separator=";">
            update sett_basic_data
            set
            status = #{item.status,jdbcType=VARCHAR},
            callback_status = #{item.callbackStatus,jdbcType=VARCHAR},
            update_time = #{item.updateTime,jdbcType=TIMESTAMP}
            where biz_order_no = #{item.bizOrderNo,jdbcType=VARCHAR}
            and biz_type = #{item.bizType,jdbcType=VARCHAR}
            and fund_type = #{item.fundType,jdbcType=VARCHAR}
        </foreach>
    </update>

在jdbc鏈接數據庫時添加一下配置
?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true

親手採過的坑。
這事因爲原來mysql的批量更新是要我們主動去設置的, 就是在數據庫的連接url上設置一下,加上* &allowMultiQueries=true *即可。

字段映射

將表中的字段與我們建立的entity實體進行建立關聯

通過resultMap來映射字段名和實體類屬性名的一一對應的關係

<select id="getOrder" parameterType="int" resultMap="orderresultmap">
        select * from orders where order_id=#{id}
</select>
 
//type對對應的實體類
<resultMap type=”me.gacl.domain.order” id=”orderresultmap”>
  <!–用id屬性來映射主鍵字段–>
  <id property=”id” column=”order_id”/>

  <!–用result屬性來映射非主鍵字段,property爲實體類屬性名,column爲數據表中的屬性–>
  <result property = “orderno” column =”order_no”/>
  <result property=”price” column=”order_price” />
</reslutMap>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章