在项目中遇到一个场景:为了减少响应时间,将从数据库读取出来的数据读取到内存中(使用变量Map实现),对数据的操作就在内存中进行,而不用去数据库中进行。同时,带来的问题是操作后的数据如何更新到数据库,这个问题的解决方式目前是设置数据的存活时间和刷新时间。
缓存单元代码
以下是实现数据缓存单元的代码:
package org.ghostcloud.cn.mysql.jdbc.common.util;
import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 把数据预先缓存到内存,缩短响应时间
*/
public class DataMapUtil {
//容器,保存class 图标、描述信息
private static final Map<String, CacheData> CACHE_DATA = new ConcurrentHashMap<>();
/**
* 缓存数据实体
*/
private static class CacheData {
private String iconPath;
private String description;
public CacheData(String iconPath, String description) {
this.iconPath = iconPath;
this.description = description;
}
public String getIconPath() {
return iconPath;
}
public void setIconPath(String iconPath) {
this.iconPath = iconPath;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
/**
* 新增数据
*
* @param className
* @param iconPath
* @param description
*/
public static void setData(String className, String iconPath, String description) {
CACHE_DATA.put(className, new CacheData(iconPath, description));
}
/**
* 删除对应className
*
* @param classNames
*/
public static void deleteData(List<String> classNames) {
if (classNames != null && !classNames.isEmpty()) {
classNames.forEach(a -> CACHE_DATA.remove(a));
}
}
/**
* 更新对应className
*
* @param originClassName
* @param newClassName
*/
public static void updateClassName(String originClassName, String newClassName) {
CacheData data = CACHE_DATA.get(originClassName);
if (data != null) {
deleteData(Collections.singletonList(originClassName));
CACHE_DATA.put(newClassName, data);
}
}
/**
* 根据className获取图标
*
* @param className
* @return
*/
public static String getClassIconPath(String className) {
CacheData cacheData = CACHE_DATA.get(className);
if (cacheData == null) {
return null;
}
File file = new File(FileUtil.iconPathDir, cacheData.getIconPath());
return cacheData.getIconPath();
}
/**
* 根据key删除数据
* @param key
*/
public static void clear(String key) {
CACHE_DATA.remove(key);
}
/**
* 清空缓存容器
*/
public static void clearAll() {
CACHE_DATA.clear();
}
/**
* 获取数据集合大小
* @return
*/
public static int getDataSize() {
return CACHE_DATA.size();
}
}
数据库操作方法,调用缓存单元类方法实例
public void loadClassList(String projectName) {
String sql = String.format("select `id`, `class_name`, `project_name`, `icon_path`, `description`, `create_time`, `update_time` from class_management where project_name = '%s' order by `update_time` desc;", projectName);
List<List<String>> tempList = new ArrayList<>();
try (Connection connection = DBUtil.getConnection();
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql)) {
//每次载入否清除掉上个工程的缓存数据
DataMapUtil.clearAll();
while (resultSet.next()) {
List<String> temp = new ArrayList<>();
//class_name
String className = resultSet.getString(2);
//icon_path
String iconPath = resultSet.getString(4);
//description
String description = resultSet.getString(5);
//载入内存数据
DataMapUtil.setData(className, iconPath, description);
}
} catch (Exception e) {
throw new ProjectException(String.format("数据库查询异常: %s", ExceptionUtil.getExceptionAllInformation(e)));
}
}
/**
* 根据className,projectName 更新对应class的类名
*
* @param className
* @param projectName
*/
@Override
public void updateClass(String className, String newClassName, String projectName) {
//这里考虑是否data过大
//SQL语句支持的大小
String updateSql = String.format("update class_management set `class_name` = '%s' where `class_name` = '%s' and `project_name` = '%s';",
newClassName, className, projectName);
try (Connection connection = DBUtil.getConnection();
Statement statement = connection.createStatement();) {
statement.executeUpdate(updateSql);
//更新map
DataMapUtil.updateClassName(className, newClassName);
} catch (Exception e) {
throw new ProjectException(String.format("数据库异常: %s", ExceptionUtil.getExceptionAllInformation(e)));
}
}
/**
* 根据className,projectName 删除对应className
*
* @param classNames
* @param projectName
*/
@Override
public void deleteClass(List<String> classNames, String projectName) {
if (classNames == null || classNames.isEmpty()) {
return;
}
classNames.forEach(className -> {
try (Connection connection = DBUtil.getConnection();
Statement statement = connection.createStatement();) {
String deleteSql = String.format("delete from class_management where `class_name` ='%s' and `project_name` = '%s' ", className, projectName);
statement.executeUpdate(deleteSql);
} catch (Exception e) {
throw new ProjectException(String.format("数据库异常: %s", ExceptionUtil.getExceptionAllInformation(e)));
}
});
//删除对应缓存
DataMapUtil.deleteData(classNames);
}
/**
* 存入class到数据库
*
* @param className
* @param iconPath
* @param description
* @param projectName
*/
@Override
public void saveClass(String className, String iconPath, String description, String projectName) {
//SQL语句支持的大小
String saveSql = String.format("insert into class_management(`class_name`, `icon_path`, description , `project_name` ) values('%s' , '%s', '%s', '%s')", className, iconPath, description, projectName);
try (Connection connection = DBUtil.getConnection();
Statement statement = connection.createStatement();) {
statement.execute(saveSql);
DataMapUtil.setData(className, iconPath, description);
} catch (Exception e) {
throw new ProjectException(String.format("数据库录入异常: %s", ExceptionUtil.getExceptionAllInformation(e)));
}
}