zoukankan      html  css  js  c++  java
  • mybatis的复习01

    1、MyBatis是手动提交事务
    测试1:

    @Test
    public void testInsert() throws Exception {

    // 1.创建SqlSession对象
    SqlSession session = MyBatisUtil.openSession();

    // 2.创建UserMapper接口的代理对象
    UserMapper userMapper = session.getMapper(UserMapper.class);

    // 3. 执行UserMapper的insert方法
    User user = new User(null, "张无忌1111", "123", 25);
    System.err.println("执行之前 :" + user);
    userMapper.insert(user);
    System.out.println("执行之后 :" + user);

    // 4.提交事务(MyBatis是手动提交事务)

    session.commit();

    // 5.关闭Session
    session.close();
    }


    结果:
    数据库有记录

    测试2:
    将 session.commit();去掉后,数据库没有记录了。

    --------------------------------------------------------------------------------


    2、mybatis缓存

    1、mybatis自带的二级缓存:
    <cache type="org.apache.ibatis.cache.impl.PerpetualCache"/>,PerpetualCache这个类是mybatis默认实现缓存功能的类。我们不写type就使用mybatis默认的缓存
    参阅:(建议去看这个blog,比下面的好看)
    https://www.cnblogs.com/ysocean/p/7342498.html

    2、二级缓存的原理及配置
    二级缓存的原理和一级缓存原理一样,第一次查询,会将数据放入缓存中,然后第二次查询则会直接去缓存中取。但是一级缓存是基于 sqlSession 的,而 二级缓存是基于 mapper文件的namespace的,也就是说多个sqlSession可以共享一个mapper中的二级缓存区域,并且如果两个mapper的namespace相同,即使是两个mapper,那么这两个mapper中执行sql查询到的数据也将存在相同的二级缓存区域中。
      

      那么二级缓存是如何使用的呢?
      ①、开启二级缓存
      和一级缓存默认开启不一样,二级缓存需要我们手动开启
      首先在全局配置文件 mybatis-configuration.xml 文件中加入如下代码:
    1234 <!--开启二级缓存  --><settings>    <setting name="cacheEnabled" value="true"/></settings>
      其次在 UserMapper.xml 文件中开启缓存
    12 <!-- 开启二级缓存 --><cache></cache>
      我们可以看到 mapper.xml 文件中就这么一个空标签<cache/>,其实这里可以配置<cache type="org.apache.ibatis.cache.impl.PerpetualCache"/>,PerpetualCache这个类是mybatis默认实现缓存功能的类。我们不写type就使用mybatis默认的缓存,也可以去实现 Cache 接口来自定义缓存。
      

      

      我们可以看到 二级缓存 底层还是 HashMap 架构。


      ②、po 类实现 Serializable 序列化接口
      


      开启了二级缓存后,还需要将要缓存的pojo实现Serializable接口,为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样,不一定只存在内存中,有可能存在硬盘中,如果我们要再取这个缓存的话,就需要反序列化了。所以mybatis中的pojo都去实现Serializable接口。
      
      ③、测试
      一、测试二级缓存和sqlSession 无关
    12345678910111213141516171819 @Testpublic void testTwoCache(){    //根据 sqlSessionFactory 产生 session    SqlSession sqlSession1 = sessionFactory.openSession();    SqlSession sqlSession2 = sessionFactory.openSession();         String statement = "com.ys.twocache.UserMapper.selectUserByUserId";    UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);    UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);    //第一次查询,发出sql语句,并将查询的结果放入缓存中    User u1 = userMapper1.selectUserByUserId(1);    System.out.println(u1);    sqlSession1.close();//第一次查询完后关闭sqlSession         //第二次查询,即使sqlSession1已经关闭了,这次查询依然不发出sql语句    User u2 = userMapper2.selectUserByUserId(1);    System.out.println(u2);    sqlSession2.close();}
      可以看出上面两个不同的sqlSession,第一个关闭了,第二次查询依然不发出sql查询语句。

      二、测试执行 commit() 操作,二级缓存数据清空
    1234567891011121314151617181920212223242526 @Testpublic void testTwoCache(){    //根据 sqlSessionFactory 产生 session    SqlSession sqlSession1 = sessionFactory.openSession();    SqlSession sqlSession2 = sessionFactory.openSession();    SqlSession sqlSession3 = sessionFactory.openSession();         String statement = "com.ys.twocache.UserMapper.selectUserByUserId";    UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);    UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);    UserMapper userMapper3 = sqlSession2.getMapper(UserMapper.class);    //第一次查询,发出sql语句,并将查询的结果放入缓存中    User u1 = userMapper1.selectUserByUserId(1);    System.out.println(u1);    sqlSession1.close();//第一次查询完后关闭sqlSession         //执行更新操作,commit()    u1.setUsername("aaa");    userMapper3.updateUserByUserId(u1);    sqlSession3.commit();         //第二次查询,由于上次更新操作,缓存数据已经清空(防止数据脏读),这里必须再次发出sql语句    User u2 = userMapper2.selectUserByUserId(1);    System.out.println(u2);    sqlSession2.close();}
      查看控制台情况:


    3、二级缓存整合ehcache
    mybatis自带的二级缓存,但是这个缓存是单服务器工作,无法实现分布式缓存。那么什么是分布式缓存呢?假设现在有两个服务器1和2,用户访问的时候访问了1服务器,查询后的缓存就会放在1服务器上,假设现在有个用户访问的是2服务器,那么他在2服务器上就无法获取刚刚那个缓存,如下图所示:
      


    为了解决这个问题,就得找一个分布式的缓存,专门用来存储缓存数据的,这样不同的服务器要缓存数据都往它那里存,取缓存数据也从它那里取,如下图所示:
      

     上文一开始提到过,mybatis提供了一个cache接口,如果要实现自己的缓存逻辑,实现cache接口开发即可。mybatis本身默认实现了一个,但是这个缓存的实现无法实现分布式缓存,所以我们要自己来实现。ehcache分布式缓存就可以,mybatis提供了一个针对cache接口的ehcache实现类,这个类在mybatis和ehcache的整合包中。
      ①、导入 mybatis-ehcache 整合包(最上面的源代码中包含有)
      


      ②、在全局配置文件 mybatis-configuration.xml 开启缓存
    1234 <!--开启二级缓存  --><settings>    <setting name="cacheEnabled" value="true"/></settings>
      
      ③、在 xxxMapper.xml 文件中整合 ehcache 缓存
      将如下的类的全类名写入<cache type="" ></cache>的type属性中
    12345 <!-- 开启本mapper的namespace下的二级缓存    type:指定cache接口的实现类的类型,不写type属性,mybatis默认使用PerpetualCache    要和ehcache整合,需要配置type为ehcache实现cache接口的类型--><cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
      
      ④、配置缓存参数
      在 classpath 目录下新建一个 ehcache.xml 文件,并增加如下配置:
    123456789101112131415161718 <?xml version="1.0" encoding="UTF-8"?><ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">     <diskStore path="F:developehcache"/>     <defaultCache            maxElementsInMemory="10000"            eternal="false"            timeToIdleSeconds="120"            timeToLiveSeconds="120"            maxElementsOnDisk="10000000"            diskExpiryThreadIntervalSeconds="120"            memoryStoreEvictionPolicy="LRU">        <persistence strategy="localTempSwap"/>    </defaultCache>     </ehcache>
      
    diskStore:指定数据在磁盘中的存储位置。
    defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
    以下属性是必须的:
    maxElementsInMemory - 在内存中缓存的element的最大数目
    maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
    eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
    overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
    以下属性是可选的:
    timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
    timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
    diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
    diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
    diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
    memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)


  • 相关阅读:
    写了一个分页控件。
    职业规划
    程序员该做的事
    做就做最优秀的员工
    Tomcat+JSP经典配置实例
    2005年11月26日8点50左右,南昌地震。
    如何添加一个自定义的columnstyles 到设计器中,以便在设计时直接使用他们?
    Oracle 的入门心得【强烈推荐】
    如何随机显示记录条数的15% ?
    重写DataGrid的DataGridBoolColumn,添加bool值改变事件。
  • 原文地址:https://www.cnblogs.com/dxwen/p/11252307.html
Copyright © 2011-2022 走看看