Mybatis3.2.3 知識點快速摘要
摘要: 基於mybatis官網上的doc整理了一個快速摘要
Mybatis的好處
- 節省了JDBC方式下手寫代碼的工作量, 主要的節省在於自動按照resultMap返回結果類型的對象或對象集合甚至Map;
- 對sql語句直接編寫方便DBA或程序員自己對sql語句優化
- 相對hibernate映射ORM的方式, 學習成本低
Mybatis環境搭建
- 核心包: 十分簡潔方便, 只用一個mybatis-x.x.x.jar
- 依賴包: 主要就是logging用的包, 提供了對各種方式logging的支持
- 配置文件: 需要兩種配置文件
§ 全局配置文件: 數據開發環境配置, mybatis性能配置, mapper資源索引
§ Mapper配置文件: 一種sql存儲流程的配置, 包括配置輸入參數, sql語句模塊, 結果的類型配置
Mybatis 全局配置
上圖是Mybatis全局配置的一個簡易視圖:彩色模塊是常用主要配置,無背景色部分配置較少(一些高級的配置),這裏忽略介紹.
<properties>
用於加載一些配置用的properties文件以及在整個配置文件開頭定義一些需要用到的屬性常量用於全局的引用
<propertiesresource="mysql.properties"> <propertyname="username"value="root"/> <property name="password"value="root"/> </properties> |
<typeAliases>
此處指定一些全局可用的類型的別名主要爲了簡化書寫, 這些typeAliases可以在mapper文件中被type/resultType屬性引用.
<typeAliases> <typeAliastype="cn.itcast.mybatis.User"alias="user"/> <typeAliastype="cn.itcast.mybatis.Order"alias="order"/> </typeAliases> |
<environments>
配置JDBC數據庫連接的環境配置信息:
幾點注意的是:
- 可以配置多個<environment>, 在<environments>- default屬性上指定應用哪個
- 配置數據庫連接需要: dataSource和transactionManager
- dataSource有3種type配置: POOLED|UNPOOLED|JNDI: 選擇POOLED
- transactionManager有2種type配置: JDBC|MANAGED 和第三方整合時,選擇MANAGED
<environments> <environmentid="development"> <transactionManagertype="JDBC"> <propertyname="..."value="..."/> </transactionManager> <dataSourcetype="POOLED"> <propertyname="driver"value="${driver}"/> <propertyname="url"value="${url}"/> <propertyname="username"value="${username}"/> <propertyname="password"value="${password}"/> </dataSource> </environment> </environments> |
<mapper>
配置所有mapper配置文件的路徑
<mappers> <mapperresource="user.xml" /> <mapperresource="order.xml" /> </mappers> |
Mapper配置文件
Mapper的配置就像一個函數的執行過程, 定義參數, 選擇執行語句, 定義輸出的接受類型,函數中可以調用動態sql以增強sql語言的表達能力.
parameterType
這個是<select/insert/update/delete>的一個屬性: 可選的輸入有3種類型的參數容器實體,基本類型,指定的用戶自定義類型,map的鍵值對組合
需要說明的是:在這個文件中,parameterTpye只是負責定義Type的, 實際的參數容器實體的傳入是通過mybatis的javaAPI調用的時候傳入的
Sql語句中獲取參數的方式有: #{paramName} 和 ${paramName}兩種:
- #{}方式的取值採用PreparedStatement的方式替換”?“部分的sql
- ${}方式的採用字符串拼接(“…”+param+”…”)的方式拼接成完整的sql
- map或者用戶自定義類型的parameterType必須保證#/${}內的paramName是map的一個鍵或者對應用戶自定義類型(JavaBean)的一個getter的屬性名稱
<select id="findByUserId" parameterType="int" resultMap="userRM" > select * from user u,orders o where u.user_id=#{id} </select> |
<select id="findUserByCondition" parameterType="map" resultMap="userRM"> select * from user u,orders o where u.user_name=#{name} and u.user_age= #{age} </select> |
<update id="updateUser" parameterType="cn.itcast.mybatis.User"> update user t set t.user_name=#{name} where t.user_id=#{id} </update> |
<select/insert/update/delete>
此部分滿足sql語法規範, 需要注意的一點就是何時使用#{}傳參, 何時使用${}傳參: - LIKE %${paramName}%: 此處用拼接 - ORDERBY ${paramName}: 此處用拼接 |
動態Sql語句的增強
- <sql>: 提供一個sql語句片段的重用
<sql id="userFullColumns"> user_id,user_name,user_age </sql> |
- <where><if>:用於選擇性查詢時空值查詢的問題,當有where是, 自動處理and拼接問題, 當if不存在一樣寫sql語句即可
select <includerefid="userFullColumns"/> from user u <where> <if test="name != null"> u.user_name like '%${name}%' </if> <if test="age != null"> and u.user_age=#{age} </if> </where> |
- <set><if>: 用於update是屬性爲null的空值替換問題,會自動處理,的拼接問題,當if不存在一樣書寫sql語句即可
update user t <set> <if test="name!=null">t.user_name=#{name},</if> <if test="age!=null">t.user_age=#{age}</if> </set> where t.user_id=#{id} |
- <foreach> : 用於in(xxx,xxx,xxx)或者批量插入的情景,可以設置open,close, seperator, item, ofType等
select <includerefid="userFullColumns"/> from user where user_id in <foreachcollection="list"open="("close=")" item="id" separator=","> #{id} </foreach> |
<resultMap>
resultMap指定了一個結果輸出的樣式. 結果的輸出有兩種樣式,另一種是resultType,可以指定一個類型,一般是一個自定義的JavaBean.其實當指定結果樣式是resultType時, 默認生成一個resultMap,這個resultMap的自動將column每個字段(字段的別名)的值去JavaBean中尋找響應的setter,如果恰好JavaBean的setter的屬性名稱和表的column的字段(別名)名稱一致就可以匹配輸出.
而自定義resultMap就是設定JavaBean和表的映射關係. 我們需要考慮:
- 構造函數初始化注入: <constructor>:避免暴露一些屬性的setter來初始化
- 主鍵: <id>
- 普通的屬性: <result>
- 如果存在外鍵關係映射:
o <collection> :property+column+ofType+[javaType]+[resultMap]+[select]
§ javaTpye不定義, mybatis也可以自己解析
§ 如果抽取了ofType的resultMap,可以用resultMap
§ 如果結果是由另一個查詢得到的, 即用select指定一個子查詢
o <association>:property+column+[javaType]+[resultType]+[select] 同理
注意:當resultMap分佈在不同的mapper配置文件中時, 是無法相互引用的.
<collectionproperty="posts"ofType="domain.blog.Post"> <id property="id" column="post_id"/> <result property="subject" column="post_subject"/> <result property="body" column="post_body"/> </collection> <! -- 抽取resultMap --> <collectionproperty="posts"resultMap="post"/> <resultMapid="post"type="domain.blog.Post"> <idproperty="id"column="post_id"/> <resultproperty="subject"column="post_subject"/> <resultproperty="body"column="post_body"/> </resultMap> |
<resultMap id="blogResult" type="Blog"> <collectionproperty="posts"javaType="ArrayList"column="id"ofType="Post" select="selectPostsForBlog"/> </resultMap>
<select id="selectBlog" parameterType="int" resultMap="blogResult"> SELECT * FROM BLOG WHERE ID = #{id} </select>
<select id="selectPostsForBlog" parameterType="int"resultType="Blog"> SELECT * FROM POST WHERE BLOG_ID = #{id} </select> |
- 條件結果容器選擇:<discriminate>
o Discriminate用來甄別選擇哪種類型resultMap作爲結果的接受容器
o 一種實際的應用場景是: 數據庫中的一個類型選擇字段, 而且有一些公用的字段數據,那麼,抽取一個commonMap,在commonMap中針對這個類型選擇字段result_type的<discriminator>,類型類別的<resultMapextends=”commonMap”/>, 這樣,選中的類型就可以擁有公共的字段和自己獨有字段,而沒有匹配的只包含commonMap中的屬性.
<resultMap id="vehicleResult" type="Vehicle"> <id property="id" column="id" /> <result property="vin" column="vin"/> <result property="year" column="year"/> <result property="make" column="make"/> <result property="model" column="model"/> <result property="color" column="color"/> <discriminatorjavaType="int"column="vehicle_type"> <case value="1"resultMap="carResult"/> <case value="2" resultMap="truckResult"/> <case value="3" resultMap="vanResult"/> <case value="4" resultMap="suvResult"/> </discriminator> </resultMap>
<resultMap id="carResult" type="Car" extends="vehicleResult"> <result property="doorCount" column="door_count" /> </resultMap>
|
- columnPrefix屬性: 當返回的結果爲了區分開各個表中的字段而起了不同的前綴別名時,用columnPrefix=”xxx”來過濾特定的屬性字段
<resultMap id="blogResult" type="Blog"> <idproperty="id"column="blog_id"/> <resultproperty="title"column="blog_title"/> <associationproperty="author"resultMap="authorResult"/> <associationproperty="coAuthor"resultMap="authorResult" columnPrefix="co_"/> </resultMap> |
MyBatis核心初始化流程
public class QuickStartTest { // 只是一個實例,沒有進行異常的處理, 關流應try-catch-finally SqlSession session; String ns="cn.itcast.mybatis.User."; @Before public void setup() throws IOException{ String resource="config.xml"; InputStream in=Resources.getResourceAsStream(resource); SqlSessionFactory sessionFactory = newSqlSessionFactoryBuilder().build(in); session = sessionFactory.openSession(); } @Test public void test() throws IOException{ //配置過resultType後就無需強轉 User user = session.selectOne("cn.itcast.mybatis.User.findByUserId",1); System.out.println(user); } @After public void cleanup(){ session.close(); } } |