Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
import org.tuna.zoopzoop.backend.domain.datasource.dto.DataSourceSearchCondition;
import org.tuna.zoopzoop.backend.domain.datasource.dto.DataSourceSearchItem;
import org.tuna.zoopzoop.backend.domain.datasource.entity.Category;
import org.tuna.zoopzoop.backend.domain.datasource.entity.DataSource;
import org.tuna.zoopzoop.backend.domain.datasource.entity.QDataSource;
import org.tuna.zoopzoop.backend.domain.datasource.entity.QTag;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -89,15 +90,15 @@ public Page<DataSourceSearchItem> search(Integer memberId, DataSourceSearchCondi

// content
JPAQuery<Tuple> contentQuery = queryFactory
.select(ds.id, ds.title, ds.dataCreatedDate, ds.summary, ds.source, ds.sourceUrl, ds.imageUrl, ds.category)
.select(ds.id, ds.title, ds.createDate, ds.summary, ds.source, ds.sourceUrl, ds.imageUrl, ds.category)
.from(ds)
.join(ds.folder, folder)
.join(pa).on(pa.archive.eq(folder.archive))
.where(where.and(ownership));

List<OrderSpecifier<?>> orderSpecifiers = toOrderSpecifiers(pageable.getSort());
if (!orderSpecifiers.isEmpty()) contentQuery.orderBy(orderSpecifiers.toArray(new OrderSpecifier<?>[0]));
else contentQuery.orderBy(ds.createDate.desc());
else contentQuery.orderBy(ds.createDate.desc()); // 기본 정렬: 생성일시 내림차순

List<Tuple> tuples = contentQuery.offset(pageable.getOffset()).limit(pageable.getPageSize()).fetch();
Long totalCount = countQuery.fetchOne();
Expand All @@ -123,7 +124,7 @@ public Page<DataSourceSearchItem> search(Integer memberId, DataSourceSearchCondi
.map(row -> new DataSourceSearchItem(
row.get(ds.id),
row.get(ds.title),
row.get(ds.dataCreatedDate),
row.get(ds.createDate).toLocalDate(),
row.get(ds.summary),
row.get(ds.source),
row.get(ds.sourceUrl),
Expand All @@ -140,16 +141,16 @@ public Page<DataSourceSearchItem> search(Integer memberId, DataSourceSearchCondi
private List<OrderSpecifier<?>> toOrderSpecifiers(Sort sort) {
if (sort == null || sort.isEmpty()) return List.of();

PathBuilder<org.tuna.zoopzoop.backend.domain.datasource.entity.DataSource> root =
new PathBuilder<>(org.tuna.zoopzoop.backend.domain.datasource.entity.DataSource.class, "dataSource");
PathBuilder<DataSource> root =
new PathBuilder<>(DataSource.class, "dataSource");

List<OrderSpecifier<?>> specs = new ArrayList<>();
for (Sort.Order o : sort) {
Order dir = o.isAscending() ? Order.ASC : Order.DESC;
switch (o.getProperty()) {
case "title" -> specs.add(new OrderSpecifier<>(dir, root.getString("title")));
case "createdAt" -> specs.add(
new OrderSpecifier<>(dir, root.getDate("dataCreatedDate", LocalDate.class))
new OrderSpecifier<>(dir, root.getDateTime("createDate", LocalDateTime.class))
);
default -> { /* 무시 */ }
}
Expand Down Expand Up @@ -207,7 +208,8 @@ public Page<DataSourceSearchItem> searchInArchive(Integer archiveId, DataSourceS

// content
JPAQuery<Tuple> contentQuery = queryFactory
.select(ds.id, ds.title, ds.dataCreatedDate, ds.summary, ds.source, ds.sourceUrl, ds.imageUrl, ds.category)
// 이미 공유 쪽은 createDate 사용 중
.select(ds.id, ds.title, ds.createDate, ds.summary, ds.source, ds.sourceUrl, ds.imageUrl, ds.category)
.from(ds)
.join(ds.folder, folder)
.where(where.and(scope));
Expand Down Expand Up @@ -237,7 +239,8 @@ public Page<DataSourceSearchItem> searchInArchive(Integer archiveId, DataSourceS
.map(row -> new DataSourceSearchItem(
row.get(ds.id),
row.get(ds.title),
row.get(ds.dataCreatedDate),
// LocalDateTime(createDate) → LocalDate
row.get(ds.createDate).toLocalDate(),
row.get(ds.summary),
row.get(ds.source),
row.get(ds.sourceUrl),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ public void moveMany(List<Integer> ids, int targetFolderId) {
public void hardDeleteOne(int dataSourceId) {
DataSource ds = dataSourceRepository.findById(dataSourceId)
.orElseThrow(() -> new NoResultException("존재하지 않는 자료입니다."));
deleteOwnedImageIfAny(ds);
// deleteOwnedImageIfAny(ds);
dataSourceRepository.delete(ds);
}

Expand All @@ -190,7 +190,7 @@ public void hardDeleteMany(List<Integer> ids) {
if (ids == null || ids.isEmpty()) return;
List<DataSource> list = dataSourceRepository.findAllById(ids);
if (list.size() != ids.size()) throw new NoResultException("존재하지 않는 자료 포함");
for (DataSource ds : list) deleteOwnedImageIfAny(ds);
// for (DataSource ds : list) deleteOwnedImageIfAny(ds);
dataSourceRepository.deleteAll(list);
}

Expand Down Expand Up @@ -321,19 +321,15 @@ public String uploadThumbnailAndReturnFinalUrl(MultipartFile image, String key)

// ===== S3 삭제 관련 유틸 =====
// 소유한 이미지가 있으면 S3에서 삭제
private void deleteOwnedImageIfAny(DataSource ds) {
String url = ds.getImageUrl();
if (url == null || url.isBlank()) return;
if (!isOurS3Url(url)) return;

String key = extractKeyFromUrl(url);
if (key == null || key.isBlank()) return;

try {
s3Service.delete(key);
} catch (Exception ignore) {
// 파일 삭제 실패로 전체 삭제를 롤백하지 않음
// 필요하면 warn 로그 추가
public void deleteIfOwnedByExactKey(String imageUrl, String expectedKey) {
if (imageUrl == null || imageUrl.isBlank() || expectedKey == null || expectedKey.isBlank()) return;
String key = extractKeyFromUrl(imageUrl);
if (expectedKey.equals(key)) {
try {
s3Service.delete(key);
} catch (Exception ignore) {
// S3 삭제 실패가 전체 트랜잭션을 막지 않도록 무시
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.tuna.zoopzoop.backend.domain.datasource.dto.DataSourceSearchCondition;
import org.tuna.zoopzoop.backend.domain.datasource.dto.DataSourceSearchItem;
import org.tuna.zoopzoop.backend.domain.datasource.dto.UpdateOutcome;
import org.tuna.zoopzoop.backend.domain.datasource.entity.DataSource;
import org.tuna.zoopzoop.backend.domain.datasource.entity.Tag;
import org.tuna.zoopzoop.backend.domain.datasource.repository.DataSourceRepository;

Expand Down Expand Up @@ -79,9 +80,13 @@ public int create(int memberId, String sourceUrl, Integer folderIdOrZero, DataSo
// hard delete
@Transactional
public int deleteOne(int memberId, int dataSourceId) {
dataSourceRepository.findByIdAndMemberId(dataSourceId, memberId)
DataSource ds = dataSourceRepository.findByIdAndMemberId(dataSourceId, memberId)
.orElseThrow(() -> new NoResultException("존재하지 않는 자료입니다."));

// S3 삭제
String expectedKey = domain.thumbnailKeyForPersonal(memberId, dataSourceId);
domain.deleteIfOwnedByExactKey(ds.getImageUrl(), expectedKey);

domain.hardDeleteOne(dataSourceId);
return dataSourceId;
}
Expand All @@ -98,6 +103,13 @@ public void deleteMany(int memberId, List<Integer> ids) {
missing.removeAll(new HashSet<>(existing));
throw new NoResultException("존재하지 않거나 소유자가 다른 자료 ID 포함: " + missing);
}
// S3 삭제
List<DataSource> list = dataSourceRepository.findAllById(ids);
for (DataSource ds : list) {
String expectedKey = domain.thumbnailKeyForPersonal(memberId, ds.getId());
domain.deleteIfOwnedByExactKey(ds.getImageUrl(), expectedKey);
}

domain.hardDeleteMany(ids);
}

Expand Down