MyBatis — 动态SQL、缓存机制

 

3)每个增删改标签都发生一个flushCache=”true”:增删改执行就后就会知道缓存【一流二级缓存都会见给清空】

    prefix给拼串后的全套字符串加一个前缀

中间属性:

@Test
public void TestFirstCache(){
      SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
      session = sqlSessionFactory.openSession();
      mapper = session.getMapper(EmployeeMapper.class);

      Employee emp = mapper.getEmpInfoById(4);
      System.out.println(emp);

      mapper.deleteEmp(16);

      Employee emp2 = mapper.getEmpInfoById(4);
      System.out.println(emp2);

      System.out.println(emp == emp2);

      session.commit();
      session.close();
}

                  false:不以缓存(顶尖缓存还接纳,二级缓存不使)

 2)假诺只要写下列的SQL语句,只要是无为空,就作为查询条件,如下所示,这样描绘实际是发问题之,所以大家要是描写成动态SQL语句:

 2.当EmployeeMapper.xml的sql映射文件中加上响应的讲话

然仔细来说,下面的sql语句是生问题之,当我们不吃动态sql语句传递id值的早晚,sql语句的拼装就会发出问题!【name前发出一个and】

 2.sql映射文件

LRU
–目前起码使用的:移除最丰硕时未深受拔取的靶子。

@Test
public void TestFirstCache(){
      SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
      session = sqlSessionFactory.openSession();
      mapper = session.getMapper(EmployeeMapper.class);
      Employee emp = mapper.getEmpInfoById(4);
      System.out.println(emp);

      SqlSession session2 = sqlSessionFactory.openSession();
      EmployeeMapper mapper2 = session2.getMapper(EmployeeMapper.class);
      Employee emp2 = mapper2.getEmpInfoById(4);
      System.out.println(emp2);

      System.out.println(emp == emp2);

      session.commit();
      session.close();
}

      false:非只读:mybatis觉得收获之多少或许相会给改。

foreach 中因故
collection,collection中凡是自Mapper接口传来的参数,separator是失去丢中间符号

3.消专注:where标签只会见失掉丢第一只多出去的and或者or

2.若会讲话关闭,顶尖缓存中的数量会叫保存到二级缓存中;新的对话查询音信,就足以参考二级缓存中。


trim【where,set】:字符串截取,其中where标签封装查询条件,set标签封装修改标准

flushInterval:缓存刷新间隔
?缓存多少长度期清空一浅,默认不清空,设置一个毫秒值。

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

SOFT
–软引用:移除基于垃圾回收器状态和软引用规则的目的。

– if:字符判断

二级缓存:

    后边多来之and或者or where标签不可知解决

 test从参数中取值举办判定

– foreach:

 2)去mapper.xml中布置使用二级缓存

@Test
public void TestInsertStus(){
      StudentMapper bean = ioc.getBean(StudentMapper.class);
      List<Student> list = new ArrayList<Student>();
      list.add(new Student("123","123", "123"));
      list.add(new Student("123","123", "123"));
      list.add(new Student("123","123", "123"));
      bean.insertStus(list);
}
@Test
public void TestUpdateStu(){
      StudentMapper bean = ioc.getBean(StudentMapper.class);
      bean.updateStu(new Student(4, "jackk", null, null));
}

1)在EmployeeMapper接口文件添加一个措施

 

 

<select id="getEmployeeByConditionIf" resultType="com.neuedu.entity.Employee">
       select *from tbl_employee where id = #{id} and user_name = #{userName} and email = #{email} and gender = #{gender}
</select>

一些时候需要依照要询问的参数动态的拼凑SQL语句

 

MyBatis
包含一个生强的询问缓存特性,它可死有利地配置和定制。缓存可以极大的晋级查询功用。

1.一个会话,查询同一长达数,这么些数据就是会叫放在脚下对话的一流缓存中。

    suffix给拼串后底整字符串加一个后缀

<select id="getStudent" resultType="com.neuedu.mybatis.entity.Student">
      SELECT *
      FROM student
      <trim prefix="where" prefixOverrides="and">
            <if test="id != null">
                  id=#{id}
            </if>
            <if test="name !=null and name!=''">
                  and name=#{name}
            </if>
            <if test="password !=null and password !=''">
                  and password=#{password}
            </if>
            <if test="email !=null and email !=''">
                  and email=#{email}
            </if>
      </trim>
</select>
public void updateStu(Student student);

– foreach:遍历元素

public Student getStudent(Student student);
@Test
public void TestgetStudent(){
      StudentMapper bean = ioc.getBean(StudentMapper.class);
      Student student = new Student(4,"jack", "111", "jack@qq.com");
      System.out.println(student);
      Student student2 = bean.getStudent(student);
      System.out.println(student2);
}

 

 

案例:测试一级缓存【默认是敞开的】

 3.测试代码

一流缓存:

 3)测试类代码为

type:指定由定义缓存的全类名
实现cache接口即可!

if案例

可看看仅发送了一致蹩脚SQL语句,第二涂鸦询问时自二级缓存中以到的数额,并不曾发送新的sql语句。

<cache eviction="FIFO" size="100" readOnly="false"/>

 

size:引用数,正整数,默认1024

           假诺flushCache =
true;每趟查询前还会见清空缓存,缓存是无受采纳!

即使一定给按照不同尺度更找

       
–1、默认情形下,只来顶尖缓存(SqlSession级别之缓存,也叫做本地缓存)开启。

    prefix=””:前缀:trim标签体是漫天字符串拼串后底结果。

【顶级缓存的限依然极其小了,每回SqlSession一关闭,顶尖缓存中的多寡就是消灭】

效率:数据会从二级缓存中赢得

 

2.好使用 where
标签
来拿所有的询问条件包括在内

4)必须事先关前的sqlsession对象

 一流缓存失效的意况【4种】(没有用到当前一流缓存的事态,效果尽管是,还得更朝着数据库来查询)

<update id="updateStu">
      update student
      <trim prefix="set" suffixOverrides=",">
            <if test="name !=null and name!=''">
                  name=#{name},
            </if>
            <if test="password !=null and password !=''">
                  password=#{password},
            </if>
            <if test="email !=null and email !=''">
                  email=#{email}
            </if>
      </trim>
            where id = #{id}
</update>

所以从之角度说:能跨sqlSession的缓存为二级缓存!

readOnly:是否就读,true/false

public List<Student> getStus(Student student);

 遇见特殊符号,应该去写转义字符:如<>分别吗&lt,&gt

– where 标签

         
需要小心的凡:在哪个Mapper.xml文件被开了<cache>缓存标签,哪个Mapper中即便被了二级缓存。

1.以EmployeeMapper接口类中补充加批量插入的计

1.当EmployeeMapper接口中入一个艺术

         
只有会话提交或者关闭后,顶尖缓存中的数量才谋面转移至二级缓存中。

行事机制:

 test:判断表明式(OGNL):OGNL参照PPT或者官方文档。

        –2、二级缓存需要手动开启同配备,他是基于namespace级别之休养生息存。

 

     
代表缓存最多好储存多少只对象,太可怜容易导致内存溢出

手动清除了缓存,所以得重新寻找

解决办法

<update id="updateStu">
      update student
      <set>
            <if test="name !=null and name!=''">
                  name=#{name},
            </if>
            <if test="password !=null and password !=''">
                  password=#{password},
            </if>
            <if test="email !=null and email !=''">
                  email=#{email}
            </if>
      </set>
            where id = #{id}
</update>

案例演示:

           查询标签:flushCache = “false”

极度给确保了第一只case 符合之后,就跳出

 

 

 

            与数据库同四回对话期间查询及之数据在地面缓存中。

              mybatis为了加速获取速度,直接就是会拿数据以缓存中之援交给用户。不安全,速度快。

暨缓存有关的装置/属性:

 

 foreach标签还可用来批量保存数据

1.于where后边长1=1,未来的准绳都好行使and xxx了

   mybatis就会用where标签中并装的sql,多下的and或者or去丢!

案例:

@Test
public void TestFirstCache(){
      SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
      session = sqlSessionFactory.openSession();
      mapper = session.getMapper(EmployeeMapper.class);
      Employee emp = mapper.getEmpInfoById(4);
      System.out.println(emp);
      session.close();

      SqlSession session2 = sqlSessionFactory.openSession();
      EmployeeMapper mapper2 = session2.getMapper(EmployeeMapper.class);
      Employee emp2 = mapper2.getEmpInfoById(4);
      System.out.println(emp2);
      session2.close();
}

     一流缓存:(本地缓存):SqlSession级别之缓存,顶级缓存是直接被之,没法关。方法中不一起用!


FIFO
–先进先出:按目的上缓存的依次来移除它们。

@Test
public void TestFirstCache(){
      SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
      session = sqlSessionFactory.openSession();
      mapper = session.getMapper(EmployeeMapper.class);

      Employee emp = mapper.getEmpInfoById(4);
      System.out.println(emp);

      session.clearCache();

      Employee emp2 = mapper.getEmpInfoById(4);
      System.out.println(emp2);

      System.out.println(emp == emp2);

      session.commit();
      session.close();
}

 

测试:

将返回false,说明emp2不是emp的缓存

      
       mybatis会利用系列化&反体系化的艺克隆一客。安全,速度迟滞。

特当MyBatis中,在SSM整合文件被并未因而,因为SqlSession 定义在
bean.xml中,无法再度定义SqlSession

 

 

案例演示:

       
–3、为了增强增添性。MyBatis定义了缓存接口Cache。我们得以经过兑现Cache接口来自定义二级缓存。

1.sqlSession见仁见智,重新定义SqlSession

1)cacheEnabled=”true”:
false:关闭缓存(二级缓存关闭)【一流缓存一贯可用】

 3)用if标签改写为动态SQL,如下所示:

@Test
public void TestFirstCache(){
      SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
      session = sqlSessionFactory.openSession();
      mapper = session.getMapper(EmployeeMapper.class);

      Employee emp = mapper.getEmpInfoById(4);
      System.out.println(emp);

      Employee emp2 = mapper.getEmpInfoById(16);
      System.out.println(emp2);

      System.out.println(emp == emp2);

      session.commit();
      session.close();
}

用回true,表达emp与emp2是缓存,而未是还寻找

一级缓存和二级缓存

           
以后如果需要拿到相同之数据,间接打缓存中以,没必要更夺查询数据库;

 

choose标签:分支采用,类似于Java被之带来了break的switch…case**

WEAK
–弱引用:更积极地移除基于垃圾收集器状态及弱引用规则的对象。

3.SqlSession一如既往,然则片糟查询之间进行了添删改操作【这一次增删改可能对当前数爆发影响】

坐默认自动刷新了缓存

 2)在sql映射文件中,填写相应的sql语句,如下所示【set标签可以拿字段前边的逗号去丢】

亟待小心的是:唯有顶级缓存中关闭的状下,二级缓存才会于使用。

1)在EmployeeMapper中添加一个革新的法

MyBatis-缓存机制   

 #测试结果没有问题,

    suffix=””:后缀

4)测试代码

默认的是LRU。

    suffixOverrides=””:后缀覆盖:去丢满字符串后边多余的字符

    prefixOverrides=””:前缀覆盖:去丢满字符串前边多余的字符


eviction=“FIFO”:缓存回收策略:

将回来一条select查询语句,

亟需注意的是:在哪个Mapper.xml文件被拉开了<cache>缓存标签,哪个Mapper中即便开启了二级缓存。

2.当MyBatis的sql映射文件被描写相应的代码

MyBatis系统中默认定义了简单层缓存。

@Test
public void TestFirstCache(){
      SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
      session = sqlSessionFactory.openSession();
      mapper = session.getMapper(EmployeeMapper.class);

      Employee emp = mapper.getEmpInfoById(4);
      System.out.println(emp);

      Employee emp2 = mapper.getEmpInfoById(4);
      System.out.println(emp2);

      System.out.println(emp == emp2);

      session.commit();
      session.close();
}

今非昔比namespace查出的数据会放在自己相应之复苏存着(map)   

【全局缓存】:基于namespace级别之缓存:一个namespace对应一个二级缓存。

set标签:字符串截取,可以写于trim里面**

set元素会动态前置set关键字,同时为会师去掉无关之逗号

2.SqlSession同等,但是查询条件不均等[时缓存中尚并未此数额]

<insert id="insertStus">
      insert into student (name,password,email) values
      <foreach collection="stus" item="stu" separator=",">
            (#{stu.name},#{stu.password},#{stu.email})
      </foreach>
</insert>

  
也就是说使用where标签有时候仍旧未可知化解问题之,那怎么惩罚呢?我们这里可以行使trim标签

4.SqlSession等同,手动清除了顶级缓存[缓存清空]

<select id="getStudent" resultType="com.neuedu.mybatis.entity.Student">
      SELECT *
      FROM student
      <where>
            <if test="id != null">
                  id=#{id}
            </if>
            <if test="name !=null and name!=''">
                  and name=#{name}
            </if>
            <if test="password !=null and password !=''">
                  and password=#{password}
            </if>
            <if test="email !=null and email !=''">
                  and email=#{email}
            </if>
      </where>
</select>
public void insertStus(@Param("stus")List<Student> student);

– choose【when…otherwise】:分支采取

 将set标签用trim标签代替

      true:只念缓存;mybatis认为颇具自缓存中获取数据的操作都是独自读操作,不谋面窜数据。

<select id="getStus" resultType="com.neuedu.mybatis.entity.Student">
      select * from student
      <where>
            <choose>
                  <when test="id !=null">
                        id = #{id}
                  </when>
                  <when test="name !=null and name!=''">
                        name = #{name}
                  </when>
                  <when test="password !=null and password!=''">
                        password = #{password}
                  </when>
                  <when test="email !=null and email!=''">
                        email = #{email}
                  </when>
                  <otherwise>
                        1 = 1
                  </otherwise>
            </choose>
      </where>
</select>

用重返两漫漫select语句

public List<Student> getStuByIdForEach(@Param("ids")List<Integer> ids);

foreach元素允许指定一个碰面,讲明集合项和目录变量,并得以指定开闭匹配的字符串以及当迭代里边放置分隔符。

 

 

     二级缓存(全局缓存):

常用标签:

@Test
public void getStuByIdForEach(){
      StudentMapper bean = ioc.getBean(StudentMapper.class);
      List<Integer> list = Arrays.asList(16,17,18,19);
      List<Student> stuByIdForEachlist = bean.getStuByIdForEach(list);
      for (Student student : stuByIdForEachlist) {
            System.out.println(student);
      }
}

 

 

trim标签:可以从定义字符串的截取规则** 

          查出的数码还相会吃默认先在一级缓存中。

1.当EmployeeMapper接口中补充加一个道

1)开启全局二级缓存配置:

2)每个select标签还起useCache=”true”;

 

<select id="getStuByIdForEach" resultType="com.neuedu.mybatis.entity.Student">
      select * from student
      where id
      in
      <foreach collection="ids" item="id" open="(" close=")" separator=",">
            #{id}
      </foreach>
</select>

3)我们的POJO需要实现类别化接口[implements Serializable]

<select id="getStudent" resultType="com.neuedu.mybatis.entity.Student">
      SELECT *
      FROM student
       where
            <if test="id != null">
                  id=#{id}
            </if>
            <if test="name !=null and name!=''">
                  and name=#{name}
            </if>
            <if test="password !=null and password !=''">
                  and password=#{password}
            </if>
            <if test="email !=null and email !=''">
                  and email=#{email}
            </if>
</select>

动态SQL的此外一个常用之操作是需要针对一个凑举行遍历,通常在构建in条件语句的早晚!

 3.测试类代码

网站地图xml地图