mybatis的知識點:
1.mybatis和hibernate本質區別和應用場景
hibernate:是一個標准的ORM框架(Ojbect relation mapper對象關系映射).入門門檻較高的,不需要程序員寫sql,
sql語句自動生成了。對sql語句進行優化,修改比較困難。
應用場景:
適用於需求變化不多的中小型項目.比如后台管理,erp,orm,oa..
mybatis:專注於sql本身,需要程序員自己編寫sql語句,sql修改,優化比較方便,mybatis是一個不完全的ORM框架,
雖然程序員自己寫sql,mybatis也可以實現映射(輸入映射,輸出映射)
應用場景:
適用於需求變化較多的項目,比如:互聯網項目
2.sqlSession:是一個面向用戶(程序員)的接口
sqlSession中提供了很多操作數據的方法.如:selectOne(返回單個對象),selectList(返回單個或多個對象)
sqlSession是線程不安全的,在sqlSession實現了除了接口有的方法(操作數據庫的方法)還有數據域屬性
sqlSession最佳應用場合在方法體內,定義成局部變量使用。
3.總結原始dao開發的問題(User.xml)
1.dao接口實現類方法中存在大量模板方法,設想能否將這些代碼提取出來,大大減輕程序員的工作量
2.調用sqlsession方法是將statement的id硬編碼了 3.調用sqlsession方法是傳入的變量,由於sqlsession方法使用泛型,即使變量傳入錯誤,在編譯階段也不報錯。
不利於程序員開發
4.mapper代理方法(程序員只需要mapper接口(相當於dao接口))
1.還需要編寫mapper.xml映射文件(同時切記要在sqlMapConfig.xml里面加上這個)
2.程序員只需要開發mapper接口需要遵循一些開發規范,mybatis可以自動生成mapper接口實現類的代理對象
開發規范:
1.在mapper.xml中namespace等於mapper接口地址
<!-- namespace命名空間,作用就是對sql進行分類化管理,理解sql隔離-->
<!--注意:使用mapper代理方法開發,namespace有特殊重要的作用-->
<mapper namespace="cn.wj.test.mybatis.mapper.UserMapper">
2.mapper.java接口中的方法名和mapper.xml中statement的id一致 3.mapper.java接口中的方法輸入參數類型和mapper.xml中parameterType指定的類型一致 4.mapper.java接口中方法的返回值的類型和mapper.xml中statement中resultType的類型一致
例如:
mapper.java接口方法:
//根據id查詢查詢用戶(此時這個方法名要和statement的id保持一致)
public User findUserById(int id) throws Exception;
UserMapper.xml:
1 <select id="findUserById" parameterType="int" resultType="cn.wj.test.mybatis.pojo.User"> 2 select * from user where id = #{id} 3 </select>
在sqlMapper.xml添加UserMapper.xml映射
總結:以上的開發規范主要是對下邊代碼進行統一的生成
3.代理對象內部調用selectOne或selectList
如果mapper方法返回單個pojo對象(非集合對象),代理對象內部通過selectOne查詢數據庫
如果mapper方法返回集合對象,代理對象內部通過selectList查詢數據庫
4.mapper接口方法參數只能有一個是否影響系統開發
mapper接口方法參數只有一個,系統是否不利於擴展維護?
答:系統框架中,dao層的代碼是被業務員公用的
即使mapper接口中只有一個參數,也可以使用包裝類型的pojo滿足不同的業務方法的需求 注意:持久層方法的參數可以是包裝類型,
map...,service方法中建議不要使用包裝類型(不利於業務層的可擴展)
5.sqlMapConfig.xml中配置文件的內容和順序如下:
properties(屬性)
settings(全局配置參數)
typeAliases(類型別名)
typeHandlers(類型處理器)
objectFactory(對象工廠)
plugins(插件)
1.properties(屬性)
需求: 將數據庫連接參數單獨配置在db.properties中,只需要在sqlMapConfig.xml中加載dp.properties的屬性值,
在sqlMapperConfig.xml就不需要對數據庫的連接參數進行編碼了
properties特性:
注意:mybatis將按照下面的順序加載屬性
1.在properties元素體內定義的屬性首先揮別讀取
2.然后會讀取properties元素中resource或url加載的屬性,他會覆蓋已讀取的同名屬性
3.最后讀取parameterType傳遞的屬性,他會覆蓋已讀取的同名屬性
建議:
不要在properties元素體內添加任何屬性值,只將屬性值定義在prperties中,在properties文件中屬性名一定有一定的特性:如xxxx.xxx.xx
例子:
1.db.properties(這個里面就是屬性名就是比較特殊,例如jdbc.driver,jdbc。url)
1 jdbc.driver=com.mysql.jdbc.Driver 2 jdbc.url=jdbc:mysql://localhost:3306/mybatisData?characterEncoding=utf-8 3 jdbc.username=root 4 jdbc.password=root
sqlMapConfig文件中:
1 <!-- 加載屬性文件 --> 2 <properties resource="db.properties"> 3 <!--properties中可以配置一些屬性名和屬性值--> 4 <!--<property name="" value=""/>--> 5 </properties> 6 <dataSource type="POOLED"> 7 <property name="driver" value="${jdbc.driver}"/> 8 <property name="url" value="${jdbc.url}"/> 9 <property name="username" value="${jdbc.username}"/> 10 <property name="password" value="${jdbc.password}"/> 11 </dataSource> 12 (其中加載這個文件properties,則底下dataSource里面的參數則是property)
2.settings(配置)
mybatis全局配置參數,全局參數將會影響mybatis運行行為
3.typeAliases(別名)
需求:
在mapper.xml中定義了很多的statement,statement需要指定參數的類型,需要resultMap指定輸出結果的映射類型
如果在指定類型時輸入類型全路徑,不方便進行開發,可以針對parameterType或resultType指定的類型定義的一些別名,在mapper.xml通過別名定義,方便開發。
1 <typeAliases> 2 <!-- 3 針對單個別名的定義 4 type:類型的路徑 5 alias:別名 6 --> 7 <typeAlias type="cn.wj.test.mybatis.pojo.User" alias="user"/> 8 <!-- 9 批量定義別名(較為常用) 10 指定包名,mybatis自動掃描包中的po類,自動定義別名,別名就是類名(首字母大小寫都可) 11 --> 12 <package name="cn.wj.test.mybatis.pojo"/> 13 </typeAliases> 14 引用別名: 15 <select id="findUserById" parameterType="int" resultType="user"> 16 select * from user where id = #{id} 17 </select>
4.typeHandlers(類型處理器)
mybatis中通過typeHandlers完成jdbc類型和java類型的轉換。
通常情況下,mybatis提供的類型處理器滿足日常的需要,不需要我們自定義轉換
5.mappers(mapper的映射配置)
1.通過resource來加載單個的映射文件
<!--通過resource方法一次加載一個映射文件-->
<mapper resource="mapper/UserMapper.xml"/>
2.通過mapper接口加載映射文件
<!--
通過mapper接口加載映射文件
遵循一些規范:需要將mapper接口類名和mapper.xml映射文件保持一致,且在一個目錄中
上邊的規范是mapper接口加載映射文件
-->
<mapper class="cn.wj.test.mybatis.mapper.UserMapper"/>
3.批量添加mapper(包名,推薦使用)
<!--
批量加載mapper
指定mapper接口的包名,mybatis自動掃描包下面所有的mapper接口進行加載
上邊的規范是mapper接口加載映射文件
-->
<package name="cn.wj.test.mybatis.mapper"/>
6.輸入映射
通過parameterType指定輸入參數的類型,類型可以是簡單類型,hashmap,poji的包裝對象
需求:
完成用戶信息的綜合查詢,需要傳入的查詢條件很復雜(可能包括用戶信息,其他信息,比如商品,訂單)
針對
UserMapper.xml
1 <!-- 2 用戶的綜合查詢 3 #{userCustom.sex}:取出包裝類型的值 4 ${userCustom.username}:取出pojo包裝類型對象的名稱 5 --> 6 <select id="findUserList" parameterType="cn.wj.test.mybatis.pojo.UserQueryVo" resultType="cn.wj.test.mybatis.pojo.UserCustom"> 7 select * from user where user.sex = #{userCustom.sex} and username like '%${userCustom.username}%' 8 </select>
UserMapper.java
1 //用戶信息的綜合查詢 2 public List<UserCustom> findUserList(UserQueryVo userQueryVo) throws Exception; 3 4 測試代碼: 5 @Test 6 public void testfindUserList()throws Exception{ 7 SqlSession sqlSession = sqlSessionFactory.openSession(); 8 //創建UserMapper對象,mybatis自動生成mapper對象 9 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 10 //調用userMapper的方法 11 UserCustom userCustom = new UserCustom(); 12 userCustom.setSex("m"); 13 userCustom.setUsername("123"); 14 UserQueryVo userQueryVo = new UserQueryVo(); 15 userQueryVo.setUserCustom(userCustom); 16 List<UserCustom> userList = userMapper.findUserList(userQueryVo); 17 System.out.println(userList); 18 }
7.輸出映射
1.resultType:
使用resultType進行輸出映射,只有查詢出來的列名和pojo中的屬性名保持一致,該列才可以映射成功。
如果查詢出來的列名和pojo中的屬性名全部不一致,沒有創建pojo對象
只要查詢出來的列名和pojo中的屬性有一個一致,就會創建pojo對象。
輸出簡單類型:切記:輸出簡單類型只有一行一列的數據
2.resultMap:
mybatis中使用resultMap完成高級輸出結果映射
resultMap使用方法:
如果查詢出來的列名和pojo的屬性名不一致,通過定義一個resultMap列名和pojo屬性名做一個映射關系
1.定義resultMap
UserMapper.xml
1 <!-- 2 定義resultMap 3 將select id id_,username username_和User中的屬性作為一個映射關系 4 type:resultMap最終映射的java對象類型,可以使用別名 5 id:對resultMap的唯一標識 6 --> 7 <resultMap id="userResultMap" type="cn.wj.test.mybatis.pojo.User"> 8 <!-- 9 id表示查詢結果集中唯一標識 10 column:查詢出來的列名 11 property:type指定的pojo類型中的屬性名 12 最終resultMap對column和property做一個映射關系(對應關系) 13 --> 14 <id column="id_" property="id"/> 15 <!-- 16 result:標識對於普通名的映射 17 column:查詢出來的列名 18 property:type指定的pojo類型中的屬性名 19 最終resultMap對column和property做一個映射關系(對應關系) 20 --> 21 <result column="username_" property="username"></result> 22 </resultMap>
2.使用resultMap作為statement的輸出映射類型(返回參數使用resultMap)
1 <!-- 2 使用resultMap來進行輸出的映射 3 resultMap:指定定義的resultMap的id,如果這個resultMap在其他mapper文件中,前邊需要加namespace 4 --> 5 <select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap"> 6 select id id_,username username_ from user where id = #{id} 7 </select>
userMapper.java中的接口調用
//根據用戶信息查詢用戶列表,根據resultMap輸出
public User findUserByIdResultMap(int id) throws Exception;
小節:
使用resultType進行輸出映射,只有查詢出來的列名和pojo中的屬性名一致,該列才可以映射成功。
如果查詢出來的列名和pojo屬性名不一致,通過定義一個resultMap隊列名和pojo屬性名之間做一個映射關系。
8.動態sql
1.什么是動態sql:
mybatis核心:對sql語句進行靈活的操作,通過表達式進行判斷,對sql進行靈活的拼接,組裝。
原來的查詢語句:
1 <select id="findUserList" parameterType="cn.wj.test.mybatis.pojo.UserQueryVo" resultType="cn.wj.test.mybatis.pojo.UserCustom"> 2 select * from user where user.sex = #{userCustom.sex} and username like '%${userCustom.username}%' 3 </select>
現在的查詢語句
理由:由於原來的查詢語句可能userCustom是null或者里面的參數為‘’,所以我們可以使用動態sql來進行判斷
1 <select id="findUserList" parameterType="cn.wj.test.mybatis.pojo.UserQueryVo" resultType="cn.wj.test.mybatis.pojo.UserCustom"> 2 <!-- 3 where可以自動去掉條件中的第一個add 4 --> 5 <where> 6 <if test="userCustom != null"> 7 <if test="userCustom.sex != null and userCustom.sex = ''"> 8 and user.sex = #{userCustom.sex} 9 </if> 10 <if test="userCustom.username != null and userCustom.username = ''"> 11 and username like '%${userCustom.username}%' 12 </if> 13 </if> 14 </where> 15 </select>
9.動態sql代碼段
將上邊實現的動態sql判斷代碼塊抽取出來,組成一個sql片段,其他的statement就可以引用sql片段
1.定義sql片段
<!--
定義sql片段
id:sql片段的唯一標識
經驗:是基於單表來定義sql片段,這樣的話sql片段的可重用性才高
在slq片段中不要包括where
-->
sql片段定義:
1 <sql id="query_user_where"> 2 <if test="userCustom != null"> 3 <if test="userCustom.sex != null and userCustom.sex = ''"> 4 and user.sex = #{userCustom.sex} 5 </if> 6 <if test="userCustom.username != null and userCustom.username = ''"> 7 and username like '%${userCustom.username}%' 8 </if> 9 </if> 10 </sql> 11 sql片段引用: 12 <select id="findUserList" parameterType="cn.wj.test.mybatis.pojo.UserQueryVo" resultType="cn.wj.test.mybatis.pojo.UserCustom"> 13 <!--select * from user where user.sex = #{userCustom.sex} and username like '%${userCustom.username}%'username--> 14 select * from user 15 <!-- 16 where可以自動去掉條件中的第一個add 17 --> 18 <where> 19 <!--引用sql片段的id,如果refid指定的id不在本mapper文件中,需要前邊加namespace--> 20 <include refid="query_user_where"></include> 21 </where> 22 </select>
foreach標簽
向sql傳遞數據或List,mybatis使用foreach解析
兩種方法:
select * from user where (id = 1 or id =2)
select * from user where id in (1 , 2)
foreach的sql片段:
<sql id="query_user_where"> <if test="userCustom != null"> <if test="ids != null"> <!-- 使用foreach遍歷ids collection:指定輸入對象中集合屬性 item:每個遍歷生成的對象中 open:開始遍歷時拼接的串 close:結束遍歷時拼接的串 separator:遍歷中兩個對象需要拼接的串 --> <!-- 方法一: 使用實現下邊的sql拼接: AND (id = 1 OF id = 10) --> <foreach collection="ids" item="item_id" open="and (" close=")" separator="or"> <!--每個遍歷需要拼接的串--> id = #{item_id} </foreach> 或者我們也可以才去這種方法 <!-- 方法二: 使用實現下邊的sql拼接: And id in (1,10) --> <foreach collection="ids" item="item_id" open="and id in (" close=")" separator=","> <!--每個遍歷需要拼接的串--> #{item_id} </foreach> </if> </if> </sql> UserMapper.xml的sql片段的調用 <select id="selectUserByForeach" parameterType="cn.wj.test.mybatis.pojo.UserQueryVo" resultType="cn.wj.test.mybatis.pojo.User"> select * from user <where> <include refid="query_user_foreach"/> </where> </select>