feat(puzzle): 添加拼图模块缓存仓库并集成缓存功能

- 新增 PuzzleRepository 缓存仓库类,提供模板和元素的 Redis 缓存功能
- 实现模板按 ID 和编码的双向缓存,减少数据库查询压力
- 实现元素列表按模板 ID 缓存,避免重复查询
- 在模板服务中集成缓存,更新和删除时自动清除相关缓存
- 在生成服务中使用缓存读取模板和元素数据
- 添加缓存过期机制,设置 24 小时自动过期
- 实现批量缓存清除功能,支持按模式删除缓存
This commit is contained in:
2026-01-01 21:39:43 +08:00
parent f8374519c3
commit 21d8c56e82
3 changed files with 298 additions and 13 deletions

View File

@@ -10,9 +10,9 @@ import com.ycwl.basic.puzzle.entity.PuzzleGenerationRecordEntity;
import com.ycwl.basic.puzzle.entity.PuzzleTemplateEntity;
import com.ycwl.basic.puzzle.fill.FillResult;
import com.ycwl.basic.puzzle.fill.PuzzleElementFillEngine;
import com.ycwl.basic.puzzle.mapper.PuzzleElementMapper;
import com.ycwl.basic.puzzle.mapper.PuzzleGenerationRecordMapper;
import com.ycwl.basic.puzzle.mapper.PuzzleTemplateMapper;
import com.ycwl.basic.puzzle.repository.PuzzleRepository;
import com.ycwl.basic.puzzle.service.IPuzzleGenerateService;
import com.ycwl.basic.puzzle.util.PuzzleDuplicationDetector;
import com.ycwl.basic.puzzle.util.PuzzleImageRenderer;
@@ -51,8 +51,7 @@ import java.util.concurrent.TimeUnit;
@Service
public class PuzzleGenerateServiceImpl implements IPuzzleGenerateService {
private final PuzzleTemplateMapper templateMapper;
private final PuzzleElementMapper elementMapper;
private final PuzzleRepository puzzleRepository;
private final PuzzleGenerationRecordMapper recordMapper;
private final PuzzleImageRenderer imageRenderer;
private final PuzzleElementFillEngine fillEngine;
@@ -63,15 +62,14 @@ public class PuzzleGenerateServiceImpl implements IPuzzleGenerateService {
public PuzzleGenerateServiceImpl(
PuzzleTemplateMapper templateMapper,
PuzzleElementMapper elementMapper,
PuzzleRepository puzzleRepository,
PuzzleGenerationRecordMapper recordMapper,
@Lazy PuzzleImageRenderer imageRenderer,
@Lazy PuzzleElementFillEngine fillEngine,
@Lazy ScenicRepository scenicRepository,
@Lazy PuzzleDuplicationDetector duplicationDetector,
@Lazy PrinterService printerService) {
this.templateMapper = templateMapper;
this.elementMapper = elementMapper;
this.puzzleRepository = puzzleRepository;
this.recordMapper = recordMapper;
this.imageRenderer = imageRenderer;
this.fillEngine = fillEngine;
@@ -104,8 +102,8 @@ public class PuzzleGenerateServiceImpl implements IPuzzleGenerateService {
// 1. 参数校验
validateRequest(request);
// 2. 查询模板
PuzzleTemplateEntity template = templateMapper.getByCode(request.getTemplateCode());
// 2. 查询模板(使用缓存)
PuzzleTemplateEntity template = puzzleRepository.getTemplateByCode(request.getTemplateCode());
if (template == null) {
throw new IllegalArgumentException("模板不存在: " + request.getTemplateCode());
}
@@ -148,8 +146,8 @@ public class PuzzleGenerateServiceImpl implements IPuzzleGenerateService {
// 参数校验
validateRequest(request);
// 1. 查询模板和元素
PuzzleTemplateEntity template = templateMapper.getByCode(request.getTemplateCode());
// 1. 查询模板和元素(使用缓存)
PuzzleTemplateEntity template = puzzleRepository.getTemplateByCode(request.getTemplateCode());
if (template == null) {
throw new IllegalArgumentException("模板不存在: " + request.getTemplateCode());
}
@@ -161,7 +159,7 @@ public class PuzzleGenerateServiceImpl implements IPuzzleGenerateService {
// 2. 校验景区隔离
Long resolvedScenicId = resolveScenicId(template, request.getScenicId());
List<PuzzleElementEntity> elements = elementMapper.getByTemplateId(template.getId());
List<PuzzleElementEntity> elements = puzzleRepository.getElementsByTemplateId(template.getId());
if (elements.isEmpty()) {
throw new IllegalArgumentException("模板没有配置元素: " + request.getTemplateCode());
}
@@ -246,7 +244,7 @@ public class PuzzleGenerateServiceImpl implements IPuzzleGenerateService {
Long resolvedScenicId,
PuzzleGenerationRecordEntity record,
long startTime) {
List<PuzzleElementEntity> elements = elementMapper.getByTemplateId(template.getId());
List<PuzzleElementEntity> elements = puzzleRepository.getElementsByTemplateId(template.getId());
if (elements.isEmpty()) {
throw new IllegalArgumentException("模板没有配置元素: " + request.getTemplateCode());
}

View File

@@ -12,6 +12,7 @@ import com.ycwl.basic.puzzle.entity.PuzzleElementEntity;
import com.ycwl.basic.puzzle.entity.PuzzleTemplateEntity;
import com.ycwl.basic.puzzle.mapper.PuzzleElementMapper;
import com.ycwl.basic.puzzle.mapper.PuzzleTemplateMapper;
import com.ycwl.basic.puzzle.repository.PuzzleRepository;
import com.ycwl.basic.puzzle.service.IPuzzleTemplateService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -37,6 +38,7 @@ public class PuzzleTemplateServiceImpl implements IPuzzleTemplateService {
private final PuzzleTemplateMapper templateMapper;
private final PuzzleElementMapper elementMapper;
private final PuzzleRepository puzzleRepository;
@Override
@Transactional(rollbackFor = Exception.class)
@@ -70,6 +72,7 @@ public class PuzzleTemplateServiceImpl implements IPuzzleTemplateService {
}
// 如果修改了编码,检查新编码是否已存在
String oldCode = existing.getCode();
if (request.getCode() != null && !request.getCode().equals(existing.getCode())) {
int count = templateMapper.countByCode(request.getCode(), id);
if (count > 0) {
@@ -82,6 +85,12 @@ public class PuzzleTemplateServiceImpl implements IPuzzleTemplateService {
entity.setId(id);
templateMapper.update(entity);
// 清除缓存(如果修改了code,需要同时清除新旧code的缓存)
puzzleRepository.clearTemplateCache(id, oldCode);
if (request.getCode() != null && !request.getCode().equals(oldCode)) {
puzzleRepository.clearTemplateCache(null, request.getCode());
}
log.info("拼图模板更新成功: id={}", id);
}
@@ -100,6 +109,9 @@ public class PuzzleTemplateServiceImpl implements IPuzzleTemplateService {
templateMapper.deleteById(id);
elementMapper.deleteByTemplateId(id);
// 清除缓存
puzzleRepository.clearTemplateCache(id, existing.getCode());
log.info("拼图模板删除成功: id={}, 同时删除了关联的元素", id);
}
@@ -196,7 +208,10 @@ public class PuzzleTemplateServiceImpl implements IPuzzleTemplateService {
// 4. 插入数据库
elementMapper.insert(entity);
log.info("元素添加成功: id={}, type={}, key={}",
// 5. 清除元素缓存
puzzleRepository.clearElementsCache(request.getTemplateId());
log.info("元素添加成功: id={}, type={}, key={}",
entity.getId(), entity.getElementType(), entity.getElementKey());
return entity.getId();
}
@@ -225,6 +240,8 @@ public class PuzzleTemplateServiceImpl implements IPuzzleTemplateService {
// 3. 批量插入
if (!entityList.isEmpty()) {
elementMapper.batchInsert(entityList);
// 4. 清除元素缓存
puzzleRepository.clearElementsCache(templateId);
log.info("批量添加元素成功: templateId={}, count={}", templateId, entityList.size());
}
}
@@ -293,6 +310,9 @@ public class PuzzleTemplateServiceImpl implements IPuzzleTemplateService {
log.info("批量替换元素完成: templateId={}, deleted={}, updated={}, inserted={}",
templateId, deletedCount, updatedCount, insertedCount);
// 7. 清除元素缓存
puzzleRepository.clearElementsCache(templateId);
}
@Override
@@ -314,6 +334,9 @@ public class PuzzleTemplateServiceImpl implements IPuzzleTemplateService {
entity.setId(id);
elementMapper.update(entity);
// 4. 清除元素缓存
puzzleRepository.clearElementsCache(existing.getTemplateId());
log.info("元素更新成功: id={}", id);
}
@@ -329,6 +352,10 @@ public class PuzzleTemplateServiceImpl implements IPuzzleTemplateService {
}
elementMapper.deleteById(id);
// 清除元素缓存
puzzleRepository.clearElementsCache(existing.getTemplateId());
log.info("元素删除成功: id={}", id);
}