動的SQLとキャッシング
動的SQL
- 動的SQLとは
- さまざまなクエリ条件に従って、さまざまなSQLステートメントを生成します
- タグを使用して、柔軟なSQLステートメントを作成します
- 基本的に、SQLステートメントをスプライシングしています
- データベーステーブルを作成する
CREATE TABLE `blog` (
`id` varchar(50) NOT NULL COMMENT '博客id',
`title` varchar(100) NOT NULL COMMENT '博客标题',
`author` varchar(30) NOT NULL COMMENT '博客作者',
`create_time` datetime NOT NULL COMMENT '创建时间',
`views` int(30) NOT NULL COMMENT '浏览量'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- コア構成ファイルとツールクラスは以前と同じです。エンティティクラスは次のとおりです。
package com.kuang.pojo;
import lombok.Data;
import java.util.Date;
@Data
public class Blog {
private String id;
private String title;
private String author;
private Date create_time;
private int views;
}
- DAOインターフェース
package com.kuang.dao;
import com.kuang.pojo.Blog;
import java.util.List;
import java.util.Map;
public interface BlogMapper {
//插入数据
int addBlog(Blog blog);
//查询博客
List<Blog> queryBlogByIf(Map map);
List<Blog> queryBlogByChoose(Map map);
//更新博客
int updateBlogBySet(Map map);
//查询第1-3号记录博客
List<Blog> queryBlogByForeach(Map map);
}
- インターフェイス実装クラス
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.dao.BlogMapper">
<!--向数据库表插入数据-->
<insert id="addBlog" parameterType="Blog">
insert into mybatis.blog(id, title, author, create_time, views)
values(#{
id}, #{
title}, #{
author}, #{
create_time}, #{
views});
</insert>
<!--sql标签的使用-->
<!--
sql片段 实际上就是将共有的片段抽离出来 需要使用的时候再引用进去
注意:
1 最好基于单表定义SQL片段
2 SQL片段不要存在where标签
-->
<sql id="if-title-author">
<if test="title!=null">
title=#{
title}
</if>
<if test="author!=null">
and author=#{
author}
</if>
</sql>
<!--动态sql语句之if和where标签的使用-->
<!--
1 满足if标签里的条件就会把语句拼接进去
2 where标签 就是检测where之后拼接的第一个语句,如果有and(or),则直接删掉and(or);如果where之后没有语句了,则直接删掉自己
-->
<select id="queryBlogByIf" parameterType="map" resultType="Blog">
select * from mybatis.blog
<where>
<!--引入sql片段-->
<include refid="if-title-author"></include>
</where>
</select>
<!--动态sql语句之choose标签的使用-->
<!--
choose就相当于switch...case...default..
只要满足其中一个,就停止
-->
<select id="queryBlogByChoose" parameterType="map" resultType="Blog">
select * from mybatis.blog
<where>
<choose>
<when test="author!=null">
author=#{
author}
</when>
<when test="title!=null">
and title=#{
title}
</when>
<otherwise>
and views=#{
views}
</otherwise>
</choose>
</where>
</select>
<!--动态sql语句之set标签的使用-->
<!--
set标签 可以删除无关的逗号 如果set之后没有修改的,它也不会删掉自己,只会报错
-->
<update id="updateBlogBySet" parameterType="map">
update mybatis.blog
<set>
<if test="views!=null">
views=#{
views},
</if>
<if test="author!=null">
author=#{
author}
</if>
</set>
where id=#{
id}
</update>
<!--动态sql语句之Foreach标签使用-->
<!--
select * from blog where 1=1 and (id=1 or id=2 or id=3);
-->
<select id="queryBlogByForeach" parameterType="map" resultType="Blog">
select * from mybatis.blog
<where>
<foreach collection="ids" item="id" open="(" close=")" separator="or">
id=#{
id}
</foreach>
</where>
</select>
</mapper>
- テストクラス
import com.kuang.dao.BlogMapper;
import com.kuang.pojo.Blog;
import com.kuang.utils.id_utils;
import com.kuang.utils.mybatis_utils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
public class mytest {
@Test
public void testAddBlog(){
SqlSession sqlsession = mybatis_utils.getSqlSession();
BlogMapper mapper = sqlsession.getMapper(BlogMapper.class);
Blog blog = new Blog();
blog.setId(id_utils.getId());
blog.setTitle("Mybatis如此简单");
blog.setAuthor("狂神说");
blog.setCreate_time(new Date());
blog.setViews(9999);
mapper.addBlog(blog);
blog.setId(id_utils.getId());
blog.setTitle("Java如此简单");
mapper.addBlog(blog);
blog.setId(id_utils.getId());
blog.setTitle("Spring如此简单");
mapper.addBlog(blog);
blog.setId(id_utils.getId());
blog.setTitle("微服务如此简单");
mapper.addBlog(blog);
sqlsession.close();
}
@Test
public void testQueryBlogByIf(){
SqlSession sqlSession=mybatis_utils.getSqlSession();
BlogMapper blogMapper=sqlSession.getMapper(BlogMapper.class);
HashMap map=new HashMap();
map.put("title","Mybatis如此简单");
map.put("author","狂神说");
List<Blog> blogList=blogMapper.queryBlogByIf(map);
for (Blog blog : blogList) {
System.out.println(blog);
}
sqlSession.close();
}
@Test
public void testQueryBlogByChoose(){
SqlSession sqlSession=mybatis_utils.getSqlSession();
BlogMapper blogMapper=sqlSession.getMapper(BlogMapper.class);
HashMap map=new HashMap();
//map.put("author","狂神说");
map.put("title","Mybatis如此简单");
map.put("views",9999);
List<Blog> blogList=blogMapper.queryBlogByChoose(map);
for (Blog blog : blogList) {
System.out.println(blog);
}
sqlSession.close();
}
@Test
public void testUpdateBlogBySet(){
SqlSession sqlSession=mybatis_utils.getSqlSession();
BlogMapper blogMapper=sqlSession.getMapper(BlogMapper.class);
HashMap map=new HashMap();
map.put("views",3333);
map.put("id","3");
int res=blogMapper.updateBlogBySet(map);
if(res>0){
System.out.println("你成功了!");
}
sqlSession.close();
}
@Test
public void testQueryBlogByForeach(){
SqlSession sqlSession=mybatis_utils.getSqlSession();
BlogMapper blogMapper=sqlSession.getMapper(BlogMapper.class);
HashMap map=new HashMap();
ArrayList<Integer> ids=new ArrayList<Integer>();
ids.add(1);
ids.add(2);
map.put("ids",ids);
List<Blog> blogList=blogMapper.queryBlogByForeach(map);
for (Blog blog : blogList) {
System.out.println(blog);
}
sqlSession.close();
}
}
キャッシュ
- キャッシングとは
- メモリに保存された一時データ
- ユーザーが頻繁にクエリし、頻繁に変更しないデータをキャッシュに入れます
- キャッシングを使用する理由
- データベースとの対話の数を減らし、システムオーバーヘッドを減らし、システム効率を向上させます
レベル1キャッシュ
- レベル1キャッシュ
- ローカルセッションキャッシュとも呼ばれます
- デフォルトオン
- SqlSessionレベルのキャッシュですか
- Sqlsessionオブジェクトの作成中、閉じられるまでのみ存在します
- 第1レベルのキャッシュ無効化とは何ですか
- 第1レベルのキャッシュの無効化とは、次のことを指します。現在の第1レベルのキャッシュは使用できません。データを照会するには、データベースへの接続要求を開始する必要があります。
- 第1レベルのキャッシュ障害の4つの状況
- sqlSessionが異なります
- 同じsqlSession、異なるものを照会する
- sqlSessionは同じです。追加、削除、変更するとキャッシュが更新されます
- sqlSessionと同じように、手動でキャッシュをクリアします
sqlsession.clearCache();
二次キャッシュ
-
二次キャッシュ
- グローバルキャッシュとも呼ばれます
- 名前名レベルのキャッシュですか
- sqlsession(セッション)が閉じられると、sqlsessionの第1レベルのキャッシュがなくなり、第1レベルのキャッシュのデータが第2レベルのキャッシュに保存されます。
-
二次キャッシュの使用
- グローバルキャッシュをオンにして、次の構成をコア構成ファイルに追加します
<setting name="cacheEnabled" value="true"/>
- mapper.xml構成ファイルでセカンダリキャッシュを構成します
<cache/>
- すべてのエンティティクラスは、最初にシリアル化インターフェイスを実装します
public class Blog implements Serializable{}
- テスト
//使用不同的sqlsession查询相同的东西 @Test public void testQueryUserById(){ SqlSession session = MybatisUtils.getSession(); SqlSession session2 = MybatisUtils.getSession(); UserMapper mapper = session.getMapper(UserMapper.class); UserMapper mapper2 = session2.getMapper(UserMapper.class); User user = mapper.queryUserById(1);//一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中 System.out.println(user); session.close();//当会话关闭以后,一级缓存数据被保存到了二级缓存中 User user2 = mapper2.queryUserById(1);//再次查询 直接从二级缓存中拿数据 System.out.println(user2); System.out.println(user==user2);//true session2.close(); }
- グローバルキャッシュをオンにして、次の構成をコア構成ファイルに追加します
キャッシングの原理
- ユーザーがデータを照会する順序
- 最初にセカンダリキャッシュがあるかどうかを確認します
- 第1レベルのキャッシュかどうかを確認します
- クエリデータベース
- 省略形:user -----> second-level cache -----> first-level cache -----> database