认识MyBatis、Mybatis笔记.MyBatis的核心配置,动态Mapper,动态SQL,表的关联及分页操作和缓存理解
Mybatis入門:
? Mybatis是一個非常優(yōu)秀的持久層掛架(類似于Spring Data JPA).它內(nèi)部封裝了通過JDBC訪問數(shù)據(jù)庫的操作,支持定制化SQL,存儲過程,高級映射
? 在IDEA中搭建MyBatis環(huán)境:
? 1.創(chuàng)建項(xiàng)目
? 2.在maven中導(dǎo)入mybatis所依賴的jar包
<!--Mybatis依賴--> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.5</version> </dependency>? 3.創(chuàng)建MyBatis的核心配置XML文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <!--在Mybatis的核心配置文件中是有先后順序的--> <configuration><!--指定數(shù)據(jù)庫鏈接信息的位置--><properties resource="jdbc.properties" /><!--自定義別名--><typeAliases><!--typeAlias:定義單個別名package:自定義掃描包里面的pojo實(shí)體類,定義別名,默認(rèn)別名(首字母小寫)--><!--<typeAlias alias="Book" type="com.mybatis.pojo.Book" />--><package name="com.mybatis.pojo" /></typeAliases><!--應(yīng)用環(huán)境們 default默認(rèn)--><environments default="development"><!--應(yīng)用環(huán)境--><environment id="development"><!--事務(wù)管理器--><transactionManager type="JDBC"/><!--數(shù)據(jù)庫連接池--><dataSource type="POOLED"><property name="driver" value="${mysql.driverClass}"/><property name="url" value="${mysql.url}"/><property name="username" value="${mysql.username}"/><property name="password" value="${mysql.password}"/></dataSource></environment></environments><!--引入映射文件--><mappers><!--包掃描映射規(guī)則要求:要求接口文件名和映射文件名相同在包掃描中,需要在resources目錄中創(chuàng)建同名同目錄結(jié)構(gòu)的文件,這樣才能掃描映射--><package name="com.mybatis.mapper"/></mappers> </configuration>? 4.創(chuàng)建數(shù)據(jù)庫配置properties文件,實(shí)體類,mapper接口和接口SQL映射的XML文件
###連接的驅(qū)動 mysql.driverClass=com.mysql.cj.jdbc.Driver ###連接的數(shù)據(jù)庫 mysql.url=jdbc:mysql://localhost:3306/servlet_zhenai?useSSL=true&serverTimezone=UTC ###用戶名 mysql.username=root ###密碼 mysql.password=root package com.mybatis.pojo;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;/*** @program: vip03SSM* @description: 實(shí)體類* @author: 高天樂* @create: 2020-08-15 19:43**/ @Data @NoArgsConstructor @AllArgsConstructor public class Book {private Integer id;private String author;private String name;private String createTime;private Double price;private Integer sales;private Integer stock; } package com.mybatis.mapper;import org.apache.ibatis.annotations.Param;import java.util.HashMap; import java.util.List;/*** @program: vip03SSM* @description: Book接口* @author: 高天樂* @create: 2020-08-15 19:52**/ public interface BookMapper {//查詢?nèi)?/span>List findAll(); } <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.mybatis.mapper.BookMapper"><select id="findAll" resultType="book">select * from web_book</select> </mapper>? 5.進(jìn)行單元測試
MyBatis核心配置參數(shù)的設(shè)置、參數(shù)綁定
在Mybatis的核心配置文件中是有先后順序的
<properties resource="jdbc.properties" /> 指定數(shù)據(jù)庫連接信息的位置 resource:寫數(shù)據(jù)庫properties的配置文件 自定義別名 <typeAliases><!-- typeAlias:定義單個別名type:里對應(yīng)實(shí)體類的全限定名alias:自定義別名不區(qū)分大小寫--><!--<typeAlias alias="Book" type="com.mybatis.pojo.Book" />--><!--package:定義多個別名.自定義掃描包里面的pojo實(shí)體類,定義別名,默認(rèn)別名(首字母小寫)name:寫實(shí)體類包所在的地址--><package name="com.mybatis.pojo" /> </typeAliases> <environments default="development"> 應(yīng)用環(huán)境們 default為默認(rèn)環(huán)境 包含environment <environment id="development"> 應(yīng)用環(huán)境 id為唯一標(biāo)識 <transactionManager type="JDBC"/> 事務(wù)管理器 <dataSource type="POOLED"> 數(shù)據(jù)庫連接池 type里面可寫其他的數(shù)據(jù)源 如Druid <!--引入映射文件--><mappers><!--mapper 映射單個文件--><!--<mapper resource="" /> resource里寫SQL映射文件的地址 --><!--映射過個文件需要 package標(biāo)簽包掃描映射規(guī)則要求:要求接口文件名和映射文件名相同在包掃描中,需要在resources目錄中創(chuàng)建同名同目錄結(jié)構(gòu)的文件,這樣才能掃描映射--><package name="com.mybatis.mapper"/></mappers>動態(tài)mapper
<mapper namespace="com.mybatis.mapper.BookMapper"> namespace:傳遞接口的映射(命名空間,對應(yīng)接口類的全限定名)| select標(biāo)簽 | 對應(yīng)SQL語句的查找 |
| update標(biāo)簽 | 對應(yīng)SQL語句的更新 |
| delete標(biāo)簽 | 對應(yīng)SQL語句的刪除 |
| insert標(biāo)簽 | 對應(yīng)SQL語句的添加 |
上面四種標(biāo)簽里的屬性的作用
| id | 唯一表示.要和接口方法名對應(yīng) |
| parameterType | 方法中參數(shù)的傳遞類型(多個不同類型的參數(shù),可以不寫) |
| resultType | 方法返回值的類型(沒有返回值可以不寫) |
| useCache | false:禁用二級緩存(對于變化頻率較高的SQL可以使用)…默認(rèn)開啟 |
| flushCache | true:刷新緩存,默認(rèn)就是true |
| resultMap | 下列單獨(dú)介紹 |
resultMap屬性
指定字段與屬性的對應(yīng)映射關(guān)系 (當(dāng)數(shù)據(jù)庫中的字段和實(shí)體類中的屬性映射不上時,通過resultMap來進(jìn)行一一映射)
<resultMap id="baseResultMap" type="book"> id:自定義唯一標(biāo)識,此id值用于對select元素resultMap屬性的引用 type:表示該resultMap的映射結(jié)果類型(實(shí)體類,如果沒有定義別名就寫類全限定名)resultMap里的子節(jié)點(diǎn)標(biāo)簽:
? id標(biāo)簽:id標(biāo)簽只定義數(shù)據(jù)庫表里的主鍵字段
? result標(biāo)簽:對應(yīng)數(shù)據(jù)庫表里的字段
? association標(biāo)簽:主要用于一對一的關(guān)聯(lián)映射操作 映射到實(shí)體類的某個 "復(fù)雜類型"屬性
? collection標(biāo)簽:用來進(jìn)行一對多的映射
總結(jié)一句話: resultMap標(biāo)簽中的子標(biāo)記有先后順序(將關(guān)聯(lián)查詢到的多條記錄映射到集合中)
| id標(biāo)簽 | column屬性:對應(yīng)數(shù)據(jù)庫表字段 property屬性:指定數(shù)據(jù)表字段名相對應(yīng)的實(shí)體類屬性名 |
| result標(biāo)簽 | column屬性:對應(yīng)數(shù)據(jù)庫表字段 property屬性:指定數(shù)據(jù)表字段名相對應(yīng)的實(shí)體類屬性名 |
| association標(biāo)簽 | column屬性:對應(yīng)數(shù)據(jù)庫表字段 property屬性:指定數(shù)據(jù)表字段名相對應(yīng)的實(shí)體類屬性名 javaType屬性:屬性的類型 對應(yīng)類的全限定名或別名 (association標(biāo)簽里的子節(jié)點(diǎn)result標(biāo)簽和上列一樣) |
| collection | property屬性:指定數(shù)據(jù)表字段名相對應(yīng)的實(shí)體類屬性名 ofType:指定映射的集合屬性中pojo的類型 |
insert操作時主鍵自增:
| keyColumn | 指定數(shù)據(jù)庫表主鍵的字段 |
| keyProperty | 指定數(shù)據(jù)庫表字段對應(yīng)的實(shí)體類屬性名 |
| userGeneratedKeys | true開啟主鍵回寫(自增) |
oracle不支持主鍵自增需要手動實(shí)現(xiàn)
<selectKey keyProperty="id" resultType="integer" order="AFTER">select last_insert_id() </selectKey>selectKey:返回主鍵值
keyProperty:pojo類中主鍵的屬性名
resultType:pojo類中主鍵屬性的類型
order:生成策略,指selectKey什么時候生成,AFTER表示之后生成
MySQL的自增原理:執(zhí)行完SQL語句之后才生成
多參數(shù)查詢:
? 方法一: 根據(jù)作者和價格來進(jìn)行查詢默認(rèn)實(shí)現(xiàn)
? 接口方法
List<T> findByAuthorAndPrice(String author ,Double price);? 映射文件:
根據(jù)作者和價格來進(jìn)行查詢根據(jù)默認(rèn)實(shí)現(xiàn) <select id="findByAuthorAndPrice" resultType="book">select * from web_book where author=#{param1} and price=#{param2} </select>? 方法一:
? 接口方法:根據(jù)作者和價格來進(jìn)行查詢注解實(shí)現(xiàn)
List<T> findByAuthorAndPrice(@Param("author") String author , @Param("price") Double price);? 映射文件: 要注意–#{author}里的參數(shù)要和@Param(“author”)注解定義的參數(shù)寫的一樣
<!--根據(jù)作者和價格來進(jìn)行查詢根據(jù)注解實(shí)現(xiàn)--> <select id="findByAuthorAndPrice" resultType="book">select * from web_book where author=#{author} and price=#{price} </select>模糊查詢的兩種方式
? 方式一: 使用${}拼接SQL語句
<select id="findByLikeName" parameterType="string" resultType="student" >select * from student where user_name like '%${username}%' </select>? 方式二:使用concat()
<select id="findByLikeName" parameterType="string" resultType="student" >select * from student where user_name like concat('%',#{username},'%') </select>SQL語句里的兩種傳值方式
| #{} | 表示占位符,會以?號的形式顯示,防止SQL注入 |
| ${} | 表示SQL拼接語句,會直接顯示出內(nèi)容.(不安全) |
| 提議 | #{}可以防止SQL注入,盡量少用${} |
區(qū)間查詢:
在查詢時有需求進(jìn)行區(qū)間查詢或在查詢價格時查詢比指定價格低或高的數(shù)據(jù).在這里是不能直接是用 > < 號的.可以按以下進(jìn)行書寫
| > | > |
| < | < |
| >= 或 <= | <![CDATA[>=]]> and <![CDATA[<=]]> |
動態(tài)SQL
1.標(biāo)簽 判斷語句
<!--if標(biāo)簽的應(yīng)用--> <select id="findByStu" parameterType="string" resultType="student"><!--select * from Student where user_name=#{arg0} and password=#{arg1}-->select * from Student where 1=1<if test="userName != null and userName != ''">and user_name=#{userName}</if><if test="password != null and password != ''">and password=#{password}</if> </select>2. 輔助標(biāo)簽,主要用于SQL的拼接
? where標(biāo)簽作用: 解決where 1=1 的問題
? 如果where標(biāo)簽后面的字符串是以and和or開頭的就移除它
<select id="findByStu1" parameterType="string" resultType="student"><!--select * from Student where user_name=#{arg0} and password=#{arg1}-->select * from Student<where><if test="userName != null and userName != ''">and user_name=#{userName}</if><if test="password != null and password != ''">and password=#{password}</if></where> </select>? set標(biāo)簽: update student set user_name=?,password=?, where id=? 去除update拼接語句后面的最后一個逗號
<update id="updateByStu" parameterType="student">update Student<set><if test="user_name != null and user_name != ''">user_name=#{user_name},</if><if test="password != null and password != ''">password=#{password},</if></set>where id = #{id} </update>? trim標(biāo)簽: where標(biāo)簽和set標(biāo)簽的功能都可以使用trim標(biāo)簽替代
? trim里的屬性:
? prefix: 添加前綴
? suffix: 添加后綴
? prefixOverrides:去除前綴
? suffixOverrides:去出后綴
<update id="updateByStu1" parameterType="student">update Student<trim prefix="set" suffixOverrides=","><if test="user_name != null and user_name != ''">user_name=#{user_name},</if><if test="password != null and password != ''">password=#{password},</if></trim>where id=#{id} </update>3.類似java中的switch語句,用于多條件分支判斷
? 多條件匹配的邏輯就要使用多分支判斷標(biāo)記
? 特征:
? choose標(biāo)簽包裹when,otherwise標(biāo)簽
? 注意:choose標(biāo)簽中至少要有一個when標(biāo)簽,0個或1個otherwise標(biāo)簽 (當(dāng)所有的when都不滿足條件時,執(zhí)行otherwise)
? 需求: 查詢操作
? 1.當(dāng)id有值時進(jìn)行id查詢
? 2.當(dāng)id沒有值是進(jìn)行用戶名查詢
? 3.當(dāng)id和用戶名都沒有值是,查詢無結(jié)果
4. 循環(huán)語句(重點(diǎn)掌握)
? collection:必填屬性,值為迭代循環(huán)的屬性名,傳遞的參數(shù)類型首字母小寫
? 傳遞參數(shù)為Map時,collection里填 _parameter,或者使用注解@Param()指定別名
? 列表和數(shù)組有默認(rèn)的別名(list/array)
? item:變量名,值為迭代對象中取出的每一個值
? index:索引,如果是Map類型時,這個值為Map的key值
? open:循環(huán)開始的字符串
? close:循環(huán)結(jié)束的字符串
? separator:循環(huán)的分割符
5.用于構(gòu)建變量
? 其主要用于模糊查詢當(dāng)中
?
關(guān)聯(lián)操作
(resultMap里的屬性和子節(jié)點(diǎn)的屬性查看上文)
一對一:
理解:在任意一方添加對方的主鍵作為外鍵
<resultMap id="baseResult" type="orders"><result column="id" property="id" /><result column="number" property="number" /><result column="createtime" property="createtime" /><result column="note" property="note" /><!--一對一--><association property="user" column="user_id" javaType="user"><result column="username" property="username" /><result column="address" property="address" /></association> </resultMap><!--一對一查詢--><select id="selectFindByIdOrder" parameterType="integer" resultMap="baseResult"><!--select * from orders where id = #{id}-->select o.*,u.username,u.address from orders oinner join t_user uon o.user_id = u.idand o.id = #{id} </select>一對多:
理解:在"多"的一方添加"一"的一方的主鍵作為外鍵
<resultMap id="baseResult" type="orders"><result column="id" property="id" /><result column="number" property="number" /><result column="createtime" property="createtime" /><result column="note" property="note" /><!--一對一--><association property="user" column="user_id" javaType="user"><result column="username" property="username" /><result column="address" property="address" /></association><!--一對多--><collection property="orderDetails" ofType="orderDetail"><result property="items_num" column="items_num" /><result property="items_id" column="items_id" /></collection> </resultMap><!--多對多查詢--><select id="selectOrdersAndOrderDetail" parameterType="integer" resultMap="baseResult"><!--select o.*,d.items_id,d.items_num,u.username,u.addressfrom orders as o, orderdetail as d, t_user as uwhere o.id=d.orders_idand o.user_id = u.idand o.id = #{id}-->select o.*,d.items_id,d.items_num,u.username,u.addressfrom (orders o inner join orderdetail d on o.id = d.orders_id)inner join t_user uon u.id = o.user_idand o.id = #{id} </select>多對多:
1:n ---- user:orders
1:n ---- orders: orderDetail
1:1 ---- orderDetail:items
n:n ---- user:items
<resultMap id="userResult" type="user"><id property="id" column="id" /><result property="username" column="username" /><result property="address" column="address" /><collection property="orders" ofType="orders" ><result property="number" column="number" /><result property="createtime" column="createtime" /><collection property="orderDetails" ofType="orderDetail"><result property="items_id" column="items_id"/><result property="items_num" column="items_num" /><association property="items" javaType="items" ><result property="itemsName" column="itemsname" /></association></collection></collection></resultMap><select id="selectByIdOrdersAndTimes" parameterType="integer" resultMap="userResult" ><!--select o.*,d.items_id,d.items_num,d.orders_id,u.username,u.address,i.itemsnamefrom orders as o, orderdetail as d, t_user as u,items as iwhere o.id=d.orders_idand o.user_id = u.idand d.items_id = i.idand u.id = #{id}-->select o.*,d.items_id,d.items_num,d.orders_id,u.username,u.address,i.itemsnamefrom ((orders as o inner join orderdetail as d on o.id=d.orders_id)inner join t_user as u on o.user_id = u.id)inner join items as ion d.items_id = i.idand u.id = #{id}</select>Mybatis的緩存
sqlSession.clearCahe(); //強(qiáng)制清除緩存
緩存中的數(shù)據(jù)(內(nèi)存中)
緩存的作用:
? 從緩存中查詢,減少了服務(wù)器的請求次數(shù),提高了查詢的效率,解決了高并發(fā)系統(tǒng)的性能問題.
? Mybatis的緩存:一級緩存/二級緩存
一級緩存:
? 會話技術(shù):cookie(客戶端) / session(服務(wù)端)
? mybatis的一級緩存的作用域是session(會話),
? myBatis默認(rèn)開啟了一級緩存操作,并且是無法關(guān)閉的
? 執(zhí)行過程:
? Mybatis執(zhí)行查詢時,首先去緩存去查找,如果能找到數(shù)據(jù)則直接返回,如果沒有則執(zhí)行SQL語句從數(shù)據(jù)庫中查詢
二級緩存:
? Mybatis的二級緩存是Mapper級別的緩存,不同的Mapper都有一個二級緩存,不同的Mapper之間的二級緩存是互不影響的
問題:
? Mybatis是如何區(qū)分不同的Mapper的二級緩存區(qū)域?
? namespace(命名空間),兩個Mapper相同的話存在相同的二級緩存區(qū)域里面
開啟二級緩存:在MyBatis核心配置中開啟 <settings><!--開啟二級緩存,全局開關(guān),這里如果是關(guān)閉狀態(tài),則在Mapper中開啟也沒用--><setting name="cacheEnabled" value="true"/> </settings>注意:
? Mybatis二級緩存需要將查詢結(jié)果映射的pojo實(shí)現(xiàn)序列化(Serializable)
實(shí)例類序列化的目的???
序列化就是對實(shí)例對象的狀態(tài)(State 對象屬性而不包括對象方法)進(jìn)行通用編碼(如格式化的字節(jié)碼)并保存,以保證對象的完整性和可傳遞性。
簡而言之:序列化,就是為了在不同時間或不同平臺的JVM之間共享實(shí)例對象
在開發(fā)過程中推薦:
? Redis / Ehcache
Mybatis的分頁插件(pageHelper)
在核心配置中配置
<plugins><!--Mybatis的分頁配置--><plugin interceptor="com.github.pagehelper.PageInterceptor" /></plugins> /*** 分頁測試*/@Testpublic void findPageTest(){BookMapper mapper = sqlSession.getMapper(BookMapper.class);//PageHelper.startPage()配置分頁 注意:需要先指定分頁的條件,在執(zhí)行查詢PageHelper.startPage(2, 10);//查詢數(shù)據(jù)List<Book> bookList = mapper.findPage();PageInfo<Book> pageInfo = new PageInfo(bookList,10);System.out.println("總記錄數(shù):" + pageInfo.getTotal());System.out.println("總頁數(shù):" + pageInfo.getPages());System.out.println("當(dāng)前頁:" + pageInfo.getPageNum());System.out.println("當(dāng)前導(dǎo)航頁碼數(shù):" + pageInfo.getNavigatePages()); // ==10,自定義了10,默認(rèn)為8List<Book> pageList = pageInfo.getList();for (Book book : pageList){System.out.println(book);}}以上為個人筆記總結(jié),有錯誤或有待添加的地方請多多點(diǎn)評
總結(jié)
以上是生活随笔為你收集整理的认识MyBatis、Mybatis笔记.MyBatis的核心配置,动态Mapper,动态SQL,表的关联及分页操作和缓存理解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P3369 (Splay树模板)
- 下一篇: 多目标优化——帕累托最优