精华内容
下载资源
问答
  • 对于查询多commit少且用户对查询结果实时性要求不高,此时采用mybatis二级缓存技术降低数据库访问量,提高访问速度。 但不能滥用二级缓存二级缓存也有很多弊端,从MyBatis默认二级缓存是关闭的就可以看出来。 二级...

    对于查询多commit少且用户对查询结果实时性要求不高,此时采用mybatis二级缓存技术降低数据库访问量,提高访问速度。

    但不能滥用二级缓存,二级缓存也有很多弊端,从MyBatis默认二级缓存是关闭的就可以看出来。
    二级缓存是建立在同一个namespace下的,如果对表的操作查询可能有多个namespace,那么得到的数据就是错误的。
    举个简单的例子:
    订单和订单详情,orderMapper、orderDetailMapper。在查询订单详情时我们需要把订单信息也查询出来,那么这个订单详情的信息被二级缓存在orderDetailMapper的namespace中,这个时候有人要修改订单的基本信息,那就是在orderMapper的namespace下修改,他是不会影响到orderDetailMapper的缓存的,那么你再次查找订单详情时,拿到的是缓存的数据,这个数据其实已经是过时的。

    根据以上,想要使用二级缓存时需要想好两个问题:
    1)对该表的操作与查询都在同一个namespace下,其他的namespace如果有操作,就会发生数据的脏读。
    2)对关联表的查询,关联的所有表的操作都必须在同一个namespace。

    展开全文
  • Mybatis的一级缓存和二级缓存是Mybatic自带的。 目的:将sql的查询结果存放于缓存内,在接下来再次查询时,会直接从缓存中取出而不是从数据库里面获取。这样会提升查询速度,但是会产生脏读。 注意:一级缓存是自动...

    Mybatis的一级缓存和二级缓存是Mybatic自带的。
    目的:将sql的查询结果存放于缓存内,在接下来再次查询时,会直接从缓存中取出而不是从数据库里面获取。这样会提升查询速度,但是会产生脏读。
    注意:一级缓存是自动开启的,二级缓存是需要手动开启的。所以开启二级缓存需要慎重考虑。(使用spring boot环境)

    一级缓存

    一级缓存是自动开启的。是sqlSession级别的缓存。个人理解就是同一个事务之内,调取两次相同sql.
    我们只要满足以下条件就可以使用一级缓存;
    1.sqlSession级别的缓存。
    2.使用@Transactional。(必须有此注解)
    此处只贴上service的代码,其余的就是普通的mvc查询代码很简单。

       @Transactional
    	public City selectCity(int id) {
         	System.out.println("第一次查询");
        	redisDao.selectAnno(id);         	//调用dao层查询方法
        	System.out.println("第二次查询");
    		return redisDao.selectAnno(id);  //调用dao层查询方法
    
    	}
    

    这样我们就可以查询sqls,spring boot中使用开启查看sql的功能.需要指定dao层的包的位置。经过测试发现两次相同的查询只会打印出一条sql.

    logging.level.com.example.redis.dao=debug
    



    二级缓存

    二级缓存是mapper级别的,只要是对一个mapper调用就可以使用二级缓存。
    在Mybatis中查询的顺序是:二级缓存----一级缓存-------数据库。


    使用redis作二级缓存

    首先连接redis,实现Cache 接口,实现接口中的方法,从redis取值和存值。这里使用了RedisTemplate 。

    public class MybatisRedisCache implements Cache {
    
    	private static Logger log = LoggerFactory.getLogger(MybatisRedisCache.class);
    	private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
    	private RedisTemplate redisTemplate;
    	private String id;
    	private static final long EXPIRE_TIME_IN_MINUTES = 30; // redis过期时间
    
    	public MybatisRedisCache(String id) {
    		if (id == null) {
    			throw new IllegalArgumentException("Cache instances require an ID");
    		}
    		this.id = id;
    	}
    
    	@Override
    	public void clear() {
    		RedisTemplate redisTemplate = getRedisTemplate();
    		redisTemplate.execute((RedisCallback) connection -> {
    			connection.flushDb();
    			return null;
    		});
    		log.debug("Clear all the cached query result from redis");
    
    	}
    
    	@Override
    	public String getId() {
    		// TODO Auto-generated method stub
    		return this.id;
    	}
    
    	@Override
    	public Object getObject(Object key) {
    		RedisTemplate redisTemplate = getRedisTemplate();
    		//ValueOperations opsForValue = redisTemplate.opsForValue();
    		log.debug("Get cached query result from redis");
    		//return opsForValue.get(key);
    		Object obj = redisTemplate.opsForValue().get(key.toString());
            return obj;
    
    	}
    	
    	
    
    	@Override
    	public ReadWriteLock getReadWriteLock() {
    		return readWriteLock;
    	}
    
    	@Override
    	public int getSize() {
    		return 0;
    	}
    
    	@Override
    	@SuppressWarnings("uncheck")
    	public void putObject(Object key, Object value) {
    		//RedisTemplate redisTemplate = getRedisTemplate();
    		//ValueOperations opsForValue = redisTemplate.opsForValue();
    		//opsForValue.set(key, value, EXPIRE_TIME_IN_MINUTES, TimeUnit.MINUTES);
    		
            redisTemplate.opsForValue().set(key.toString(), value, 2, TimeUnit.DAYS);
    
    		log.debug("Put query result to redis");
    
    	}
    
    	@Override
    	public Object removeObject(Object key) {
    		RedisTemplate redisTemplate = getRedisTemplate();
    		redisTemplate.delete(key);
    		log.debug("Remove cached query result from redis");
    		return null;
    	}
    
    	private RedisTemplate getRedisTemplate() {
    		if (redisTemplate == null) {
    			redisTemplate = ApplicationContextHolder.getBean("redisTemplate");
    		}
    		return redisTemplate;
    	}
    
    }
    

    但是RedisTemplate 不是spring提供的,不能用spring的ioc进行依赖注入,所以需要我们手写来注册RedisTemplate 。

    @Component
    public class ApplicationContextHolder implements ApplicationContextAware {
    	private static ApplicationContext applicationContext;
    
    	@Override
    	public void setApplicationContext(ApplicationContext ctx) throws BeansException {
    		applicationContext = ctx;
    	}
    
    	/**
    	 * Get application context from everywhere
    	 *
    	 * @return
    	 */
    	public static ApplicationContext getApplicationContext() {
    		return applicationContext;
    	}
    
    	/**
    	 * Get bean by class
    	 *
    	 * @param clazz
    	 * @param <T>
    	 * @return
    	 */
    	public static <T> T getBean(Class<T> clazz) {
    		return applicationContext.getBean(clazz);
    	}
    
    	/**
    	 * Get bean by class name
    	 *
    	 * @param name
    	 * @param <T>
    	 * @return
    	 */
    	@SuppressWarnings("unchecked")
    	public static <T> T getBean(String name) {
    		return (T) applicationContext.getBean(name);
    	}              
    }
    

    然后在mapper文件中开启二级缓存

    <mapper namespace="com.example.redis.dao.RedisDao">
    <!-- 开启二级缓存 -->
    <cache type="com.example.redis.cache.MybatisRedisCache"></cache> 
    	<select id="selectAnno" resultType="com.example.redis.entity.City">
    		select * from city 
    		<if test="id != null">where id = #{id}</if>
    	</select>
    	<insert id="insertIn">
    		INSERT INTO `mysql`.`city` (`id`,
    		`provinceId`, `cityName`, `description`) VALUES ('1', '1', 'aa', 'aa')
    	</insert>
    </mapper>
    

    最后需要序列化,要不会在redis存放乱码

    @Configuration
    public class RedisConfig {
    
    	@Autowired
    	private RedisTemplate redisTemplate;
    	
    	@Bean
    	public RedisTemplate redisTemplateInit() {
    		Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    		// 设置序列化Key的实例化对象
    		redisTemplate.setKeySerializer(new StringRedisSerializer());
    		// 设置序列化Value的实例化对象
    		redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    		redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer);
    		redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
    		return redisTemplate;
    	}
    }
    

    然后我们测试,在不同的sqlsession中执行同一条sql时,只有第一次会打印出sql。我们在redis中会发现,执行一次sql后会在redis存储本次的查询结果。


    展开全文
  • 一级缓存和二级缓存

    2018-10-05 21:55:38
    cpu存取速度比内存快,引入一级缓存。 ramROM相对的,RAM是掉电以后,其中才信息就消失那一种,ROM在掉电以后信息也不会消失那一种 RAM又分两种, 一种是静态RAM,SRAM;一种是动态RAM,DRAM。前者的存储速度要比...

    cpu存取速度比内存快,引入一级缓存。
    ram和ROM相对的,RAM是掉电以后,其中才信息就消失那一种,ROM在掉电以后信息也不会消失那一种
    RAM又分两种,
    一种是静态RAM,SRAM;一种是动态RAM,DRAM。前者的存储速度要比后者快得多,我们现在使用的内存一般都是动态RAM。
    缓存通常都是静态RAM,速度是非常的快,
    但是静态RAM集成度低(存储相同的数据,静态RAM的体积是动态RAM的6倍),
    价格高(同容量的静态RAM是动态RAM的四倍),
    由此可见,扩大静态RAM作为缓存是一个非常愚蠢的行为,
    但是为了提高系统的性能和速度,我们必须要扩大缓存,
    这样就有了一个折中的方法,不扩大原来的静态RAM缓存,而是增加一些高速动态RAM做为缓存,
    这些高速动态RAM速度要比常规动态RAM快,但比原来的静态RAM缓存慢,
    我们把原来的静态ram缓存叫一级缓存,而把后来增加的动态RAM叫二级缓存。

    展开全文
  • 一级缓存:   也称为本地缓存,SqlSession级别的缓存。一级缓存是一直开启的;与数据库同一次会话期间查询到的数据会放在本地缓存中。   如果需要获取相同的数据,直接从缓存中拿,不会再查数据库。   一级...

    什么是缓存:
      将数据存放在程序内存中,用于减轻数据库查询的压力,提升读取数据的速度,提高性能。
    一级缓存:
      也称为本地缓存,SqlSession级别的缓存。一级缓存是一直开启的;与数据库同一次会话期间查询到的数据会放在本地缓存中。
      如果需要获取相同的数据,直接从缓存中拿,不会再查数据库。
      一级缓存四种失效的情况:
        1.sqlSession不同。
        2.sqlSession相同,查询条件不同。因为缓存条件不同,缓存中还没有数据。
        3.sqlSession相同,在两次相同查询条件中间执行过增删改操作。(因为中间的增删改可能对缓存中数据进行修改,所以不能用)
        4.sqlSession相同,手动清空了一级缓存。
    二级缓存:
      SqlSessionFactory级别的缓存,实现不同会话中数据的共享,是一个全局变量;
      存储作用域为Mapper的namespace级别,可手动开启关闭,要在具体的mapper.xml中开启二级缓存。

    展开全文
  • 一级缓存只是相对于同一个SqlSession而言,生命周期SqlSession一致。 生命周期 MyBatis在开启一个数据库会话时,会创建一个新的SqlSession对象,SqlSession对象中会有一个新的Executor对象。Executor对象中持有...
  • mybaits提供一级缓存和二级缓存一级缓存(本地缓存) sqlSession级别的缓存。(相当于一个方法内的缓存) 二级缓存(全局缓存) 基于namespace名称空间级别的缓存.即一个mapper.xml对应一个缓存 一级缓存...
  • MyBatis的缓存机制 缓存的引入 当我们大量执行重复的查询SQL...这也就是大家常说的MyBatis一级缓存一级缓存的作用域是SqlSession。 第1种情况:同个session进行两次相同查询 代码验证 //测试一级缓存 @Test
  • Hibernate是一个持久层框架,经常访问物理数据库,为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能,hibernate出现了缓存...hibernate将缓存分为一级缓存和二级缓存 一、一级缓存: 1、Hibenate
  • hibernate一级缓存和二级缓存的区别 缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能。缓存内的数据是对物理数据源中的数据的复制...
  • 1、缓存介绍 当处理器读取数据时,首先会从缓存中查找,如果缓存有数据,那么处理器直接使用,如果缓存中中没有,则从读取速度相对慢的内存中读取,同时把... 持久层二级缓存 分布式缓存 1、一级缓存 当hibernat...
  • 什么是缓存 将数据存放在程序内存中,用于减轻...■ 一级缓存的生命周期SqlSession一致 ■ 设置为SqlSession级别的缓存,当执行insert/update/delete操作或close之后,缓存清空; mysql 拿到一个查询语句后先看缓存,
  • 缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。  缓存的介质一般是内存,所以读写速度很快。但如果缓存中存放的数据量非常大时...
  • 、为什么使用缓存: 1.ORM框架访问数据库的效率直接影响应用程序的运行速度,提升优化ORM框架的执行效率至关重要。 2.Hibernate的缓存是提升优化Hibernate执行效率的重要手段,所以学会Hibernate缓存的使用...
  • 什么是缓存?缓存是介于应用程序和物理数据源之间,是为了降低应用程序对物理数据源的访问频率,从而提高应用程序的运行性能。...hibernante缓存包括session的缓存和sessionFactory的缓存,其中sessio...
  • 什么叫缓存 将数据存放在程序内存中,用于减轻数据查询的压力,提升读取数据的速度,提高性能。 一级缓存 ■ 两个级别 SqlSession级别的缓存,实现在同一个会话中...■ 一级缓存的生命周期SqlSession一致 ...
  • 缓存:缓存是什么,解决什么问题?  位于速度相差较大的两种...1.事务范围(单Session即一级缓存)   事务范围的缓存只能被当前事务访问,每个事务都有各自的缓存,缓存内的数据通常采用相互关联的对象形式.缓存的
  • Mybatis的一级缓存和二级缓存的理解以及用法 2019-08-29 00:42  全me村的希望  阅读(...)  评论(1)  编辑  收藏 程序中为什么使用缓存?  先了解一下缓存的概念:原始意义是指...
  • 缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。  缓存的介质一般是内存,所以读写速度很快。但如果缓存中存放的数据量非常大时,...
  • 什么叫缓存 将数据存放在程序内存中,用于减轻数据查询的压力,提升读取数据的速度,提高性能。 一级缓存 ■ 两个级别 ...■ 一级缓存的生命周期SqlSession一致 ■ 设置为SqlSession级别的缓存,当执...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 836
精华内容 334
关键字:

一级缓存和二级缓存速度