Skip to content

Commit

Permalink
optimize: 剧集资源查询方法 (#726)
Browse files Browse the repository at this point in the history
* optimize: 移除缓存配置

* optimize: 剧集资源查询方法
  • Loading branch information
chivehao authored Nov 10, 2024
1 parent cf1cab4 commit 395c5e9
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 60 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

更新日志文档,版本顺序从新到旧,最新版本在最前(上)面。

# 0.19.4

## 优化

- 移除缓存配置
- 优化查询剧集附件接口

# 0.19.3

## 优化
Expand Down
69 changes: 69 additions & 0 deletions api/src/main/java/run/ikaros/api/infra/utils/ReflectUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package run.ikaros.api.infra.utils;

import java.lang.reflect.Field;
import java.util.Map;

public class ReflectUtils {

/**
* 将数据库字段名转换为驼峰命名法的 Java 字段名.
*
* @param dbFieldName 数据库字段名(如 ATTACHMENT_ID)
* @return 转换后的 Java 字段名(如 attachmentId)
*/
public static String convertToCamelCase(String dbFieldName) {
if (dbFieldName == null || dbFieldName.isEmpty()) {
return dbFieldName;
}

StringBuilder result = new StringBuilder();
boolean toUpperCase = false;

for (int i = 0; i < dbFieldName.length(); i++) {
char ch = dbFieldName.charAt(i);
if (ch == '_') {
toUpperCase = true;
} else {
if (toUpperCase) {
result.append(Character.toUpperCase(ch));
toUpperCase = false;
} else {
result.append(Character.toLowerCase(ch));
}
}
}

return result.toString();
}

/**
* Map to Object instance.
*/
public static <T> T mapToClass(Map<String, Object> map, Class<T> clazz,
boolean ignoreMissingField) {
T instance;
try {
instance = clazz.getDeclaredConstructor().newInstance();
for (Map.Entry<String, Object> entry : map.entrySet()) {
String fieldName = convertToCamelCase(entry.getKey());
Object fieldValue = entry.getValue();

Field field;
try {
field = clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldException noSuchFieldException) {
if (ignoreMissingField) {
continue;
} else {
throw noSuchFieldException;
}
}
field.setAccessible(true); // 允许访问私有字段
field.set(instance, fieldValue);
}
} catch (Exception e) {
throw new RuntimeException("Mapping failed", e);
}
return instance;
}
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version=0.19.3
version=0.19.4

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.stereotype.Service;
Expand All @@ -14,7 +12,7 @@
import reactor.core.publisher.Mono;
import run.ikaros.api.core.subject.Episode;
import run.ikaros.api.core.subject.EpisodeResource;
import run.ikaros.api.store.enums.AttachmentReferenceType;
import run.ikaros.api.infra.utils.ReflectUtils;
import run.ikaros.api.store.enums.EpisodeGroup;
import run.ikaros.server.store.entity.EpisodeEntity;
import run.ikaros.server.store.repository.AttachmentReferenceRepository;
Expand Down Expand Up @@ -47,12 +45,6 @@ public DefaultEpisodeService(EpisodeRepository episodeRepository,


@Override
@CacheEvict(value = {"episodeWithId", "episodesWithSubjectId",
"episodeWithSubjectIdAndGroupAndSeqAndName",
"episodesWithSubjectIdAndGroupAndSeq",
"episodeCountWithSubjectId", "episodeMatchingCountWithSubjectId",
"episodesWithId", "episodeWithName"
}, allEntries = true)
public Mono<Episode> save(Episode episode) {
Assert.notNull(episode, "episode must not be null");
Long episodeId = episode.getId();
Expand All @@ -69,24 +61,20 @@ public Mono<Episode> save(Episode episode) {
}

@Override
@Cacheable(value = "episodeWithId", key = "#episodeId")
public Mono<Episode> findById(Long episodeId) {
Assert.isTrue(episodeId != null && episodeId > 0, "episode id must >= 0.");
return episodeRepository.findById(episodeId)
.flatMap(episodeEntity -> copyProperties(episodeEntity, new Episode()));
}

@Override
@Cacheable(value = "episodesWithSubjectId", key = "#subjectId")
public Flux<Episode> findAllBySubjectId(Long subjectId) {
Assert.isTrue(subjectId >= 0, "'subjectId' must >= 0.");
return episodeRepository.findAllBySubjectId(subjectId)
.flatMap(episodeEntity -> copyProperties(episodeEntity, new Episode()));
}

@Override
@Cacheable(value = "episodeWithSubjectIdAndGroupAndSeqAndName",
key = "#subjectId + '-' + #group + '-' + #name")
public Mono<Episode> findBySubjectIdAndGroupAndSequenceAndName(
Long subjectId, EpisodeGroup group, Float sequence, String name) {
Assert.isTrue(subjectId >= 0, "'subjectId' must >= 0.");
Expand All @@ -99,8 +87,6 @@ public Mono<Episode> findBySubjectIdAndGroupAndSequenceAndName(
}

@Override
@Cacheable(value = "episodesWithSubjectIdAndGroupAndSeq",
key = "#subjectId + '-' + #group + '-' + #sequence")
public Flux<Episode> findBySubjectIdAndGroupAndSequence(Long subjectId, EpisodeGroup group,
Float sequence) {
Assert.isTrue(subjectId >= 0, "'subjectId' must >= 0.");
Expand All @@ -112,7 +98,6 @@ public Flux<Episode> findBySubjectIdAndGroupAndSequence(Long subjectId, EpisodeG
}

@Override
@CacheEvict(value = "episodeWithId", key = "#episodeId")
public Mono<Void> deleteById(Long episodeId) {
Assert.isTrue(episodeId >= 0, "'episodeId' must >= 0.");
return episodeRepository.findById(episodeId)
Expand All @@ -125,14 +110,12 @@ public Mono<Void> deleteById(Long episodeId) {
}

@Override
@Cacheable(value = "episodeCountWithSubjectId", key = "#subjectId")
public Mono<Long> countBySubjectId(Long subjectId) {
Assert.isTrue(subjectId >= 0, "'subjectId' must >= 0.");
return episodeRepository.countBySubjectId(subjectId);
}

@Override
@Cacheable(value = "episodeMatchingCountWithSubjectId", key = "#subjectId")
public Mono<Long> countMatchingBySubjectId(Long subjectId) {
Assert.isTrue(subjectId >= 0, "'subjectId' must >= 0.");
return databaseClient.sql("select count(e.ID) from EPISODE e, ATTACHMENT_REFERENCE ar "
Expand All @@ -145,32 +128,24 @@ public Mono<Long> countMatchingBySubjectId(Long subjectId) {


@Override
@Cacheable(value = "episodesWithId", key = "#episodeId")
public Flux<EpisodeResource> findResourcesById(Long episodeId) {
Assert.isTrue(episodeId >= 0, "'episodeId' must >= 0.");
return attachmentReferenceRepository
.findAllByTypeAndReferenceIdOrderByTypeAscAttachmentIdAsc(
AttachmentReferenceType.EPISODE, episodeId)
.flatMap(attachmentReferenceEntity ->
attachmentRepository.findById(attachmentReferenceEntity.getAttachmentId())
.map(attachmentEntity -> EpisodeResource.builder()
.episodeId(episodeId)
.attachmentId(attachmentEntity.getId())
.parentAttachmentId(attachmentEntity.getParentId())
.name(attachmentEntity.getName())
.url(attachmentEntity.getUrl())
.canRead(true)
.build())
);
return databaseClient.sql("select att_ref.ATTACHMENT_ID as attachment_id, "
+ "att.PARENT_ID as parent_attachment_id, "
+ "att_ref.REFERENCE_ID as episode_id, "
+ "att.URL as url, "
+ "att.NAME as name "
+ "from ATTACHMENT_REFERENCE att_ref, ATTACHMENT att "
+ "where att_ref.TYPE = 'EPISODE' and att_ref.REFERENCE_ID = :episodeId "
+ "and att_ref.ATTACHMENT_ID = att.ID "
+ "order by att_ref.TYPE, att_ref.ATTACHMENT_ID")
.bind("episodeId", episodeId)
.fetch()
.all()
.map(row -> ReflectUtils.mapToClass(row, EpisodeResource.class, true));
}

@Override
@CacheEvict(value = {"episodeWithId", "episodesWithSubjectId",
"episodeWithSubjectIdAndGroupAndSeqAndName",
"episodesWithSubjectIdAndGroupAndSeq",
"episodeCountWithSubjectId", "episodeMatchingCountWithSubjectId",
"episodesWithId", "episodeWithName"
}, allEntries = true)
public Flux<Episode> updateEpisodesWithSubjectId(Long subjectId, List<Episode> episodes) {
Assert.isTrue(subjectId >= 0, "'subjectId' must >= 0.");
Assert.notNull(episodes, "'episodes' must not be null.");
Expand Down

0 comments on commit 395c5e9

Please sign in to comment.