问题现象

我们从Ehcache中取出缓存的对象,之后将对象中的属性进行了修改使用。等再次从缓存中拿到对象后,发现对象的值变成了上一次调用修改后的对象了。

原因

Ehcache中缓存的是原对象的引用,所以引用的内容被修改后cache内部的值也会被修改。

解决方案

使用Ehcache的copyStrategy

Ehcache提供了copyOnRead="true" copyOnWrite="true"的配置属性。

作用是在读取或写入数据时,不使用原始数据,而是使用拷贝数据。

但是在使用该配置的时候,还要提供copyStrategy class属性,提供Copy策略。

<cache name="bannerCache" eternal="false" maxElementsInMemory="50"
overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="300"
timeToLiveSeconds="300" memoryStoreEvictionPolicy="LFU" copyOnRead="true" copyOnWrite="true">
<copyStrategy class="com.xxx.EhcacheCopyStrategy" />
</cache>

copy策略类

public class EhcacheCopyStrategy implements ReadWriteCopyStrategy<Element> {
@Override
public Element copyForWrite(Element value) {
if(value != null){
Object temp=(Serializable)value.getObjectValue();
try {
return new Element(value.getObjectKey(),deepCopy(temp));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return value;
}
@Override
public Element copyForRead(Element storedValue) {
if(storedValue != null){
Object temp=(Serializable)storedValue.getObjectValue();
try {
return new Element(storedValue.getObjectKey(),deepCopy(temp));
} catch (ClassNotFoundException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return storedValue;
} private Object deepCopy(Object src) throws IOException, ClassNotFoundException {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteOut);
out.writeObject(src); ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream in = new ObjectInputStream(byteIn);
return in.readObject();
}
}

使用immutable对象

将我们的实体类设计成immutable的,如果需要修改就创建一个新的对象。

如何构建一个immutable对象

  • 确保fields中的成员都被private final修饰;private保证内部成员不会被外部直接访问,final保证成员在初始化后不会被assigned。
  • 不提供改变成员的方法,例如setXxx。
  • 使用final修饰自定义的类,确保类中的方法不会被重写。
  • 如果类中的某个成员是mutable类型的,那么在初始化该成员或者企图用get方法从外部对其观察时,应该使用深度拷贝,确保immutable。

String类

String类是java中典型的immutable数据类型,一个String对象一旦呗new出来后,就不能被修改,否则就会报assigned错误。

StringBuilder类的对象是mutable的数据类型,当一个StringBuilder对象被创建出来之后,其内部的值是可以通过某些内部方法进行改变的。

修改Ehcache缓存中取到的值,缓存中的值也被修改了的更多相关文章

  1. 多线程查询数据,将结果存入到redis中,最后批量从redis中取数据批量插入数据库中【我】

    多线程查询数据,将结果存入到redis中,最后批量从redis中取数据批量插入数据库中 package com.xxx.xx.reve.service; import java.util.ArrayL ...

  2. 【算法与数据结构】在n个数中取第k大的数(基础篇)

    (转载请注明出处:http://blog.csdn.net/buptgshengod) 题目介绍            在n个数中取第k大的数(基础篇),之所以叫基础篇是因为还有很多更高级的算法,这些 ...

  3. Mybatis的二级缓存、使用Redis做二级缓存

    目录 什么是二级缓存? 1. 开启二级缓存 如何使用二级缓存: userCache和flushCache 2. 使用Redis实现二级缓存 如何使用 3. Redis二级缓存源码分析 什么是二级缓存? ...

  4. hibernate的二级缓存----collection和query的二级缓存

    collection二级缓存: 不使用集合的二级缓存时: 运行下面的代码: @Test public void testCollectionSecondLevelCache1(){ Departmen ...

  5. SpringBoot学习笔记(10)-----SpringBoot中使用Redis/Mongodb和缓存Ehcache缓存和redis缓存

    1. 使用Redis 在使用redis之前,首先要保证安装或有redis的服务器,接下就是引入redis依赖. pom.xml文件如下 <dependency> <groupId&g ...

  6. react+dva 全局model中异步获取数据state在组件中取不到值

    先上结论,不是取不到,是写法有问题. 全文分4部分,1是问题描述,2是一开始的解决想法(错误做法),3是问题产生原因的思考,4是正常解决方法.只想看结论直接跳4 1.问题描述 接触react dva一 ...

  7. ComboboxColumn取值——Winform中DataGridView中某一列使用下拉框

    ComboboxColumn的用法网上很多,绑定数据源都很简单,这里我遇到的是.不绑定数据源,即所有comobox的绑定都是固定的几个数据: 可以看到没有绑定任何数据源, ,在后台cs中取到下拉框的值 ...

  8. DataGrid中取HyperLinkColumn列的值,处理DataGrid中绑定的特殊字符

    DataGrid中取HyperLinkColumn列的值. /// <summary> /// 对datagrid中标签进行编码,处理特殊字符 /// </summary> / ...

  9. action中list传到JSP中取不到值的问题

    今天遇到了这个问题 action中list传到JSP中取不到值 搞了半天是因为我在JSP中取值的的时候 <s:iterator  value="shlist" var=&qu ...

随机推荐

  1. 科技爱好者周刊(第 176 期):中国法院承认 GPL 吗?

    这里记录每周值得分享的科技内容,周五发布. 本杂志开源(GitHub: ruanyf/weekly),欢迎提交 issue,投稿或推荐科技内容. 周刊讨论区的帖子<谁在招人?>,提供大量程 ...

  2. 【webpack4.0】---webpack的基本使用(二)

    一.什么是plugins plugins可以使webpack在运行到某个时刻的时候,帮你做一些事情,类似于生命周期一样 plugins,它就是一个扩展器,它丰富了wepack本身,针对是loader结 ...

  3. Linux身份鉴别机制原理

    传统的UNIX身份鉴别机制原理 传统的UNIX身份鉴别即口令认证方式,它主要通过识别用户的用户名或者UID号获取在/etc/shadow中存放的对应用户密码密文等信息,然后获取用户输入密码并采用cry ...

  4. 2022.02.04 Day1

    前言 为日后的算法面试做准备,自己也很喜欢算法这个东西,每天3~5道题. 刷题 1.leetcode 209 长度最下的子数组 题目 长度最下的子数组 大致的意思是从数组中找到长度最小的数组,并且数组 ...

  5. AT2657 [ARC078D] Mole and Abandoned Mine

    简要题解如下: 记 \(1\) 到 \(n\) 的路径为关键路径. 注意到关键路径只有一条是解题的关键,可以思考这张图长什么样子. 不难发现关键路径上所有边均为桥,因此大致上是关键路径上每个点下面挂了 ...

  6. Java8-Consumer、Supplier、Predicate和Function方法总结

    这几个接口都在 java.util.function 包下的,分别是Consumer(消费型).supplier(供给型).predicate(谓词型).function(功能性): 那么,下面,我们 ...

  7. n次单位根(n-th unit root)

    最近在看CKKS方案,里面的编码/解码用到了n次单位根,感觉基于环上的加密,很多都会用到,现在系统的学习一下! 定义 先看定义: \[z^n=1,(n=1,2,3,...) \] 该方程的根z为n次单 ...

  8. Python基础—set、copy(Day7)

    一.数据类型补充 1.str:.isspace()字符串是空格或至少是一个空格. s='alex' s1=' ' ret=s1.isspace() print(ret)执行结果:True  2.tul ...

  9. 如何在TypeScript/JavaScript项目里引入MD5校验和

    摘要:MD5校验和则是其中一种数学算法,通常是使用工具对文件计算得出的一组32 个字符的十六进制字母和数字. 本文分享自华为云社区<TypeScript/JavaScript项目里如何做MD5校 ...

  10. 操作系统实验一:进程管理(含成功运行C语言源代码)

    目录 操作系统实验一:进程管理 1.实验目的 2.实验内容 3.实验准备 3.1.1进程的含义 3.1.2进程的状态 3.1.3进程状态之间的转换 3.2 进程控制块PCB 3.2.1进程控制块的作用 ...