小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

MyBatis學(xué)習(xí)06(動(dòng)態(tài)SQL和緩存)

 小仙女本仙人 2021-06-25

10、動(dòng)態(tài)SQL

10.1 什么是動(dòng)態(tài)SQL

動(dòng)態(tài)SQL指的是根據(jù)不同的查詢條件 , 生成不同的Sql語句.

官網(wǎng)描述:
MyBatis 的強(qiáng)大特性之一便是它的動(dòng)態(tài) SQL。如果你有使用 JDBC 或其它類似框架的經(jīng)驗(yàn),你就能體會(huì)到根據(jù)不同條件拼接 SQL 語句的痛苦。例如拼接時(shí)要確保不能忘記添加必要的空格,還要注意去掉列表最后一個(gè)列名的逗號(hào)。利用動(dòng)態(tài) SQL 這一特性可以徹底擺脫這種痛苦。
雖然在以前使用動(dòng)態(tài) SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射語句中的強(qiáng)大的動(dòng)態(tài) SQL 語言得以改進(jìn)這種情形。
動(dòng)態(tài) SQL 元素和 JSTL 或基于類似 XML 的文本處理器相似。在 MyBatis 之前的版本中,有很多元素需要花時(shí)間了解。MyBatis 3 大大精簡(jiǎn)了元素種類,現(xiàn)在只需學(xué)習(xí)原來一半的元素便可。MyBatis 采用功能強(qiáng)大的基于 OGNL 的表達(dá)式來淘汰其它大部分元素。


  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

之前寫的 SQL 語句都比較簡(jiǎn)單,如果有比較復(fù)雜的業(yè)務(wù),我們需要寫復(fù)雜的 SQL 語句,往往需要拼接,而拼接 SQL ,稍微不注意,由于引號(hào),空格等缺失可能都會(huì)導(dǎo)致錯(cuò)誤。

那么怎么去解決這個(gè)問題呢?這就要使用 mybatis 動(dòng)態(tài)SQL,通過 if, choose, when, otherwise, trim, where, set, foreach等標(biāo)簽,可組合成非常靈活的SQL語句,從而在提高 SQL 語句的準(zhǔn)確性的同時(shí),也大大提高了開發(fā)人員的效率。

10.2 案例實(shí)現(xiàn)

搭建環(huán)境

新建一個(gè)數(shù)據(jù)庫表:blog

字段:id,title,author,create_time,views

CREATE TABLE `blog` (
`id` varchar(50) NOT NULL COMMENT '博客id',
`title` varchar(100) NOT NULL COMMENT '博客標(biāo)題',
`author` varchar(30) NOT NULL COMMENT '博客作者',
`create_time` datetime NOT NULL COMMENT '創(chuàng)建時(shí)間',
`views` int(30) NOT NULL COMMENT '瀏覽量'
) ENGINE=InnoDB DEFAULT CHARSET=utf8

1、創(chuàng)建Mybatis基礎(chǔ)工程

2、實(shí)體類編寫

import java.util.Date;

public class Blog {

   private String id;
   private String title;
   private String author;
   private Date createTime;
   private int views;
   //set
   //get
}

3、編寫Mapper接口及xml文件

public interface BlogMapper {
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
       PUBLIC "-////DTD Mapper 3.0//EN"
       "http:///dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.chen.mapper.BlogMapper">

</mapper>

4、mybatis核心配置文件,下劃線駝峰自動(dòng)轉(zhuǎn)換

<settings>
   <setting name="mapUnderscoreToCamelCase" value="true"/>
   <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--注冊(cè)Mapper.xml-->
<mappers>
 <mapper resource="mapper/BlogMapper.xml"/>
</mappers>

5、插入初始數(shù)據(jù)

編寫接口

//新增一個(gè)博客
int addBlog(Blog blog);

sql配置文件

<insert id="addBlog" parameterType="blog">
  insert into blog (id, title, author, create_time, views)
  values (#{id},#{title},#{author},#{createTime},#{views});
</insert>

初始化博客方法

@Test
public void addInitBlog(){
   SqlSession session = MybatisUtils.getSession();
   BlogMapper mapper = session.getMapper(BlogMapper.class);

   Blog blog = new Blog();
   blog.setId(IDUtil.genId());
   blog.setTitle("Mybatis");
   blog.setAuthor("黑馬程序員");
   blog.setCreateTime(new Date());
   blog.setViews(20);

   mapper.addBlog(blog);

   blog.setId(IDUtil.genId());
   blog.setTitle("Java");
   mapper.addBlog(blog);

   blog.setId(IDUtil.genId());
   blog.setTitle("Spring");
   mapper.addBlog(blog);

   blog.setId(IDUtil.genId());
   blog.setTitle("微服務(wù)");
   mapper.addBlog(blog);

   session.close();
}

初始化數(shù)據(jù)完畢

10.2.1 if 語句

需求:根據(jù)作者名字和博客名字來查詢博客!如果作者名字為空,那么只根據(jù)博客名字查詢,反之,則根據(jù)作者名來查詢

1、編寫接口類

//需求1
List<Blog> queryBlogIf(Map map);

2、編寫SQL語句

<!--需求1:
根據(jù)作者名字和博客名字來查詢博客!
如果作者名字為空,那么只根據(jù)博客名字查詢,反之,則根據(jù)作者名來查詢
select * from blog where title = #{title} and author = #{author}
-->
<select id="queryBlogIf" parameterType="map" resultType="blog">
  select * from blog where
   <if test="title != null">
      title = #{title}
   </if>
   <if test="author != null">
      and author = #{author}
   </if>
</select>

3、測(cè)試

@Test
public void testQueryBlogIf(){
   SqlSession session = MybatisUtils.getSession();
   BlogMapper mapper = session.getMapper(BlogMapper.class);

   HashMap<String, String> map = new HashMap<String, String>();
   map.put("title","Mybatis");
   map.put("author","黑馬程序員");
   List<Blog> blogs = mapper.queryBlogIf(map);

   System.out.println(blogs);

   session.close();
}

這樣寫我們可以看到,如果 author 等于 null,那么查詢語句為 select * from user where title=#{title},但是如果title為空呢?那么查詢語句為 select * from user where and author=#{author},這是錯(cuò)誤的 SQL 語句,如何解決呢?請(qǐng)看下面的 where 語句!

10.2.2 Where

修改上面的SQL語句;

<select id="queryBlogIf" parameterType="map" resultType="blog">
  select * from blog
   <where>
       <if test="title != null">
          title = #{title}
       </if>
       <if test="author != null">
          and author = #{author}
       </if>
   </where>
</select>

這個(gè)“where”標(biāo)簽會(huì)知道如果它包含的標(biāo)簽中有返回值的話,它就插入一個(gè)'where’。此外,如果標(biāo)簽返回的內(nèi)容是以AND 或OR 開頭的,則它會(huì)剔除掉。

10.2.3 Set

同理,上面的對(duì)于查詢 SQL 語句包含 where 關(guān)鍵字,如果在進(jìn)行更新操作的時(shí)候,含有 set 關(guān)鍵詞,我們?cè)趺刺幚砟兀?/p>

1、編寫接口方法

int updateBlog(Map map);

2、sql配置文件

<!--注意set是用的逗號(hào)隔開-->
<update id="updateBlog" parameterType="map">
  update blog
     <set>
         <if test="title != null">
            title = #{title},
         </if>
         <if test="author != null">
            author = #{author}
         </if>
     </set>
  where id = #{id};
</update>

3、測(cè)試

@Test
public void testUpdateBlog(){
   SqlSession session = MybatisUtils.getSession();
   BlogMapper mapper = session.getMapper(BlogMapper.class);

   HashMap<String, String> map = new HashMap<String, String>();
   map.put("title","動(dòng)態(tài)SQL");
   map.put("author","秦疆");
   map.put("id","9d6a763f5e1347cebda43e2a32687a77");

   mapper.updateBlog(map);


   session.close();
}

10.2.4 choose語句

有時(shí)候,我們不想用到所有的查詢條件,只想選擇其中的一個(gè),查詢條件有一個(gè)滿足即可,使用 choose 標(biāo)簽可以解決此類問題,類似于 Java 的 switch 語句

1、編寫接口方法

List<Blog> queryBlogChoose(Map map);

2、sql配置文件

<select id="queryBlogChoose" parameterType="map" resultType="blog">
  select * from blog
   <where>
       <choose>
           <when test="title != null">
                title = #{title}
           </when>
           <when test="author != null">
              and author = #{author}
           </when>
           <otherwise>
              and views = #{views}
           </otherwise>
       </choose>
   </where>
</select>

3、測(cè)試類

@Test
public void testQueryBlogChoose(){
   SqlSession session = MybatisUtils.getSession();
   BlogMapper mapper = session.getMapper(BlogMapper.class);

   HashMap<String, Object> map = new HashMap<String, Object>();
   map.put("title","Java如此簡(jiǎn)單");
   map.put("author","狂神說");
   map.put("views",9999);
   List<Blog> blogs = mapper.queryBlogChoose(map);

   System.out.println(blogs);

   session.close();
}

10.2.5 SQL片段

有時(shí)候可能某個(gè) sql 語句我們用的特別多,為了增加代碼的重用性,簡(jiǎn)化代碼,我們需要將這些代碼抽取出來,然后使用時(shí)直接調(diào)用。

提取SQL片段:

<sql id="if-title-author">
   <if test="title != null">
      title = #{title}
   </if>
   <if test="author != null">
      and author = #{author}
   </if>
</sql>

引用SQL片段:

<select id="queryBlogIf" parameterType="map" resultType="blog">
  select * from blog
   <where>
       <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
       <include refid="if-title-author"></include>
       <!-- 在這里還可以引用其他的 sql 片段 -->
   </where>
</select>

注意:

①、最好基于 單表來定義 sql 片段,提高片段的可重用性

②、在 sql 片段中不要包括 where

10.2.6 Foreach

將數(shù)據(jù)庫中前三個(gè)數(shù)據(jù)的id修改為1,2,3;

需求:我們需要查詢 blog 表中 id 分別為1,2,3的博客信息

1、編寫接口

List<Blog> queryBlogForeach(Map map);

2、編寫SQL語句

<select id="queryBlogForeach" parameterType="map" resultType="blog">
  select * from blog
   <where>
       <!--
       collection:指定輸入對(duì)象中的集合屬性
       item:每次遍歷生成的對(duì)象
       open:開始遍歷時(shí)的拼接字符串
       close:結(jié)束時(shí)拼接的字符串
       separator:遍歷對(duì)象之間需要拼接的字符串
       select * from blog where 1=1 and (id=1 or id=2 or id=3)
     -->
       <foreach collection="ids"  item="id" open="and (" close=")" separator="or">
          id=#{id}
       </foreach>
   </where>
</select>

3、測(cè)試

@Test
public void testQueryBlogForeach(){
   SqlSession session = MybatisUtils.getSession();
   BlogMapper mapper = session.getMapper(BlogMapper.class);

   HashMap map = new HashMap();
   List<Integer> ids = new ArrayList<Integer>();
   ids.add(1);
   ids.add(2);
   ids.add(3);
   map.put("ids",ids);

   List<Blog> blogs = mapper.queryBlogForeach(map);

   System.out.println(blogs);

   session.close();
}

小結(jié):其實(shí)動(dòng)態(tài) sql 語句的編寫往往就是一個(gè)拼接的問題,為了保證拼接準(zhǔn)確,我們最好首先要寫原生的 sql 語句出來,然后在通過 mybatis 動(dòng)態(tài)sql 對(duì)照著改,防止出錯(cuò)。多在實(shí)踐中使用才是熟練掌握它的技巧。

11、緩存

11.1 簡(jiǎn)介

1、什么是緩存 [ Cache ]?

  • 存在內(nèi)存中的臨時(shí)數(shù)據(jù)。
  • 將用戶經(jīng)常查詢的數(shù)據(jù)放在緩存(內(nèi)存)中,用戶去查詢數(shù)據(jù)就不用從磁盤上(關(guān)系型數(shù)據(jù)庫數(shù)據(jù)文件)查詢,從緩存中查詢,從而提高查詢效率,解決了高并發(fā)系統(tǒng)的性能問題。

2、為什么使用緩存?

  • 減少和數(shù)據(jù)庫的交互次數(shù),減少系統(tǒng)開銷,提高系統(tǒng)效率。

3、什么樣的數(shù)據(jù)能使用緩存?

  • 經(jīng)常查詢并且不經(jīng)常改變的數(shù)據(jù)。

11.2 Mybatis緩存

  • MyBatis包含一個(gè)非常強(qiáng)大的查詢緩存特性,它可以非常方便地定制和配置緩存。緩存可以極大的提升查詢效率。

  • MyBatis系統(tǒng)中默認(rèn)定義了兩級(jí)緩存:一級(jí)緩存二級(jí)緩存

    • 默認(rèn)情況下,只有一級(jí)緩存開啟。(SqlSession級(jí)別的緩存,也稱為本地緩存)
    • 二級(jí)緩存需要手動(dòng)開啟和配置,他是基于namespace級(jí)別的緩存。
    • 為了提高擴(kuò)展性,MyBatis定義了緩存接口Cache。我們可以通過實(shí)現(xiàn)Cache接口來自定義二級(jí)緩存

11.3 一級(jí)緩存

一級(jí)緩存也叫本地緩存:

  • 與數(shù)據(jù)庫同一次會(huì)話期間查詢到的數(shù)據(jù)會(huì)放在本地緩存中。
  • 以后如果需要獲取相同的數(shù)據(jù),直接從緩存中拿,沒必須再去查詢數(shù)據(jù)庫;

11.4 一級(jí)緩存失效的四種情況

一級(jí)緩存是SqlSession級(jí)別的緩存,是一直開啟的,我們關(guān)閉不了它;

一級(jí)緩存失效情況:沒有使用到當(dāng)前的一級(jí)緩存,效果就是,還需要再向數(shù)據(jù)庫中發(fā)起一次查詢請(qǐng)求!

每個(gè)sqlSession中的緩存相互獨(dú)立

當(dāng)前緩存中,不存在這個(gè)數(shù)據(jù)

因?yàn)樵鰟h改操作可能會(huì)對(duì)當(dāng)前數(shù)據(jù)產(chǎn)生影響

11.5 二級(jí)緩存

  • 二級(jí)緩存也叫全局緩存,一級(jí)緩存作用域太低了,所以誕生了二級(jí)緩存

  • 基于namespace級(jí)別的緩存,一個(gè)名稱空間,對(duì)應(yīng)一個(gè)二級(jí)緩存;

  • 工作機(jī)制

    • 一個(gè)會(huì)話查詢一條數(shù)據(jù),這個(gè)數(shù)據(jù)就會(huì)被放在當(dāng)前會(huì)話的一級(jí)緩存中;
    • 如果當(dāng)前會(huì)話關(guān)閉了,這個(gè)會(huì)話對(duì)應(yīng)的一級(jí)緩存就沒了;但是我們想要的是,會(huì)話關(guān)閉了,一級(jí)緩存中的數(shù)據(jù)被保存到二級(jí)緩存中;
    • 新的會(huì)話查詢信息,就可以從二級(jí)緩存中獲取內(nèi)容;
    • 不同的mapper查出的數(shù)據(jù)會(huì)放在自己對(duì)應(yīng)的緩存(map)中;

11.6 使用步驟

1、開啟全局緩存 【mybatis-config.xml】

<setting name="cacheEnabled" value="true"/>

2、去每個(gè)mapper.xml中配置使用二級(jí)緩存,這個(gè)配置非常簡(jiǎn)單;【xxxMapper.xml】

<cache/>

官方示例=====>查看官方文檔
<cache
 eviction="FIFO"
 flushInterval="60000"
 size="512"
 readOnly="true"/>
這個(gè)更高級(jí)的配置創(chuàng)建了一個(gè) FIFO 緩存,每隔 60 秒刷新,最多可以存儲(chǔ)結(jié)果對(duì)象或列表的 512 個(gè)引用,而且返回的對(duì)象被認(rèn)為是只讀的,因此對(duì)它們進(jìn)行修改可能會(huì)在不同線程中的調(diào)用者產(chǎn)生沖突。

結(jié)論

  • 只要開啟了二級(jí)緩存,我們?cè)谕粋€(gè)Mapper中的查詢,可以在二級(jí)緩存中拿到數(shù)據(jù)
  • 查出的數(shù)據(jù)都會(huì)被默認(rèn)先放在一級(jí)緩存中
  • 只有會(huì)話提交或者關(guān)閉以后,一級(jí)緩存中的數(shù)據(jù)才會(huì)轉(zhuǎn)到二級(jí)緩存中

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多