Skip to content

Commit 2de078f

Browse files
committed
Changed how duplicate pages are loaded [#2025]
* Added a view to easily find duplicate pages in the database.
1 parent 3d78893 commit 2de078f

File tree

11 files changed

+70
-35
lines changed

11 files changed

+70
-35
lines changed

comixed-model/src/main/java/org/comixedproject/model/library/DuplicatePage.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,11 @@
1919

2020
import com.fasterxml.jackson.annotation.JsonProperty;
2121
import com.fasterxml.jackson.annotation.JsonView;
22+
import jakarta.persistence.*;
2223
import java.util.HashSet;
2324
import java.util.Objects;
2425
import java.util.Set;
25-
import lombok.Getter;
26-
import lombok.NonNull;
27-
import lombok.RequiredArgsConstructor;
28-
import lombok.Setter;
26+
import lombok.*;
2927
import org.comixedproject.model.comicbooks.ComicDetail;
3028
import org.comixedproject.views.View;
3129

@@ -34,15 +32,26 @@
3432
*
3533
* @author Darryl L. Pierce
3634
*/
35+
@Entity
36+
@Table(name = "duplicate_pages_view")
3737
@RequiredArgsConstructor
38+
@NoArgsConstructor
3839
public class DuplicatePage {
40+
@Id
41+
@Column(name = "file_hash")
3942
@JsonProperty("hash")
4043
@JsonView(View.DuplicatePageList.class)
4144
@NonNull
4245
@Getter
4346
private String hash;
4447

45-
@JsonProperty("comics")
48+
@Column(name = "comic_count")
49+
@JsonProperty("comicCount")
50+
@JsonView(View.DuplicatePageList.class)
51+
@Getter
52+
private Long comicCount;
53+
54+
@Transient
4655
@JsonView(View.DuplicatePageList.class)
4756
@Getter
4857
@Setter
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<databaseChangeLog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
5+
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
6+
<changeSet id="012_2025_added_duplicate_pages_view.xml" author="mcpierce">
7+
8+
<preConditions onFail="MARK_RAN">
9+
<not>
10+
<viewExists viewName="duplicate_pages_view"/>
11+
</not>
12+
</preConditions>
13+
14+
<createView viewName="duplicate_pages_view">
15+
SELECT DISTINCT p.file_hash,
16+
(SELECT COUNT(DISTINCT cp.comic_book_id) FROM comic_pages cp WHERE cp.file_hash = p.file_hash) as comic_count
17+
FROM comic_pages p
18+
WHERE p.file_hash IN (SELECT file_hash FROM comic_pages GROUP BY file_hash HAVING COUNT(*) > 1)
19+
</createView>
20+
21+
</changeSet>
22+
</databaseChangeLog>

comixed-model/src/main/resources/db/migrations/2.3/changelog-2.3.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@
1717
<include file="/db/migrations/2.3/009_2261_removed_last_read_dates.xml"/>
1818
<include file="/db/migrations/2.3/010_2133_added_comic_book_batch_scrape.xml"/>
1919
<include file="/db/migrations/2.3/011_2290_added_organizing_comics_view.xml"/>
20+
<include file="/db/migrations/2.3/012_2025_added_duplicate_pages_view.xml"/>
2021

2122
</databaseChangeLog>

comixed-repositories/src/main/java/org/comixedproject/repositories/comicpages/ComicPageRepository.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ public interface ComicPageRepository extends JpaRepository<ComicPage, Long> {
6060
*
6161
* @return a list of ComicPage objects with duplicate hashes
6262
*/
63-
@Query(
64-
"SELECT DISTINCT new org.comixedproject.model.library.DuplicatePage(p.hash) FROM ComicPage p WHERE p.hash IN (SELECT d.hash FROM ComicPage d GROUP BY d.hash HAVING COUNT(*) > 1)")
63+
@Query("SELECT dp FROM DuplicatePage dp")
6564
List<DuplicatePage> getDuplicatePages(Pageable pageable);
6665

6766
@Query(

comixed-repositories/src/test/java/org/comixedproject/repositories/comicpages/ComicPageRepositoryTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@
6060
DbUnitTestExecutionListener.class
6161
})
6262
public class ComicPageRepositoryTest {
63+
public static final String TEST_NOT_DELETED_HASH = "6789ABCDEF0123456789ABCDEF012345";
6364
private static final String TEST_DUPLICATE_PAGE_HASH_1 = "F0123456789ABCDEF0123456789ABCDE";
6465
private static final String TEST_DUPLICATE_PAGE_HASH_2 = "0123456789ABCDEF0123456789ABCDEF";
6566
private static final String TEST_DUPLICATE_PAGE_HASH_3 = "123456789ABCDEF0123456789ABCDEF0";
6667
private static final List<String> TEST_DUPLICATE_PAGE_HASHES = new ArrayList<>();
6768
private static final String TEST_INVALID_HASH = "111111111AAAAAA1111111111AAAAAA1";
68-
public static final String TEST_NOT_DELETED_HASH = "6789ABCDEF0123456789ABCDEF012345";
6969
private static final String TEST_DELETED_HASH = "56789ABCDEF0123456789ABCDEF01234";
7070

7171
static {
@@ -82,7 +82,8 @@ public void testGetDuplicatePages() {
8282

8383
assertNotNull(result);
8484
assertFalse(result.isEmpty());
85-
assertEquals(2, result.size());
85+
assertEquals(10, result.size());
86+
assertTrue(result.stream().allMatch(page -> page.getComicCount() > 1L));
8687
}
8788

8889
@Test

comixed-repositories/src/test/resources/test-database.xml

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@
735735
issue_number="117"
736736
title="The Title"
737737
cover_date="2025-01-05"
738-
store_date="2025-01-05" />
738+
store_date="2025-01-05"/>
739739
<organizing_comics_view comic_book_id="1001"
740740
comic_detail_id="2001"
741741
filename="C:/users/comixeduser/Documents/comicBooks/example2.cbz"
@@ -748,7 +748,7 @@
748748
issue_number="129"
749749
title="The Other Title"
750750
cover_date="2025-01-05"
751-
store_date="2025-01-05" />
751+
store_date="2025-01-05"/>
752752
<organizing_comics_view comic_book_id="1002"
753753
comic_detail_id="2002"
754754
filename="C:/users/comixeduser/Documents/comicBooks/example3.cbz"
@@ -761,5 +761,25 @@
761761
issue_number="130"
762762
title="The Title"
763763
cover_date="2025-01-05"
764-
store_date="2025-01-05" />
764+
store_date="2025-01-05"/>
765+
<duplicate_pages_view file_hash="0123456789ABCDEF0123456789ABCDEF"
766+
comic_count="27"/>
767+
<duplicate_pages_view file_hash="123456789ABCDEF0123456789ABCDE0F"
768+
comic_count="27"/>
769+
<duplicate_pages_view file_hash="23456789ABCDEF0123456789ABCDEF01"
770+
comic_count="27"/>
771+
<duplicate_pages_view file_hash="3456789ABCDEF0123456789ABCDEF012"
772+
comic_count="27"/>
773+
<duplicate_pages_view file_hash="456789ABCDEF0123456789ABCDEF0123"
774+
comic_count="27"/>
775+
<duplicate_pages_view file_hash="56789ABCDEF0123456789ABCDEF01234"
776+
comic_count="27"/>
777+
<duplicate_pages_view file_hash="6789ABCDEF0123456789ABCDEF012345"
778+
comic_count="27"/>
779+
<duplicate_pages_view file_hash="789ABCDEF0123456789ABCDEF0123456"
780+
comic_count="27"/>
781+
<duplicate_pages_view file_hash="89ABCDEF0123456789ABCDEF01234567"
782+
comic_count="27"/>
783+
<duplicate_pages_view file_hash="9ABCDEF0123456789ABCDEF012345678"
784+
comic_count="27"/>
765785
</dataset>

comixed-services/src/main/java/org/comixedproject/service/library/DuplicatePageService.java

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,7 @@
1919
package org.comixedproject.service.library;
2020

2121
import java.util.*;
22-
import java.util.stream.Collectors;
2322
import lombok.extern.log4j.Log4j2;
24-
import org.comixedproject.model.comicbooks.ComicBook;
25-
import org.comixedproject.model.comicbooks.ComicDetail;
2623
import org.comixedproject.model.comicpages.ComicPage;
2724
import org.comixedproject.model.library.DuplicatePage;
2825
import org.comixedproject.model.net.library.LoadDuplicatePageListResponse;
@@ -58,16 +55,6 @@ public LoadDuplicatePageListResponse getDuplicatePages(
5855
final List<DuplicatePage> pages =
5956
this.comicPageRepository.getDuplicatePages(
6057
PageRequest.of(page, size, this.doCreateSort(sortBy, sortDirection)));
61-
log.trace("Build duplicate page list");
62-
for (DuplicatePage entry : pages) {
63-
log.trace("Loading comics for hash: {}", entry.getHash());
64-
final Set<ComicDetail> comics =
65-
this.comicPageRepository.getPagesWithHash(entry.getHash()).stream()
66-
.map(ComicPage::getComicBook)
67-
.map(ComicBook::getComicDetail)
68-
.collect(Collectors.toSet());
69-
entry.setComics(comics);
70-
}
7158
log.trace("Returning duplicate page list");
7259
return new LoadDuplicatePageListResponse(this.getDuplicatePageCount(), pages);
7360
}

comixed-services/src/test/java/org/comixedproject/service/library/DuplicatePageServiceTest.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ public class DuplicatePageServiceTest {
4242

4343
@Before
4444
public void setUp() {
45-
Mockito.doNothing().when(duplicatePage).setComics(comicDetailArgumentCaptor.capture());
4645
Mockito.when(duplicatePage.getHash()).thenReturn(TEST_PAGE_HASH);
4746
Mockito.when(comicBook.getComicDetail()).thenReturn(comicDetail);
4847
Mockito.when(comicPage.getComicBook()).thenReturn(comicBook);
@@ -55,8 +54,6 @@ public void testGetDuplicatePages() {
5554

5655
Mockito.when(comicPageRepository.getDuplicatePages(pageRequestArgumentCaptor.capture()))
5756
.thenReturn(duplicatePageList);
58-
Mockito.when(comicPageRepository.getPagesWithHash(Mockito.anyString()))
59-
.thenReturn(comicPageList);
6057

6158
LoadDuplicatePageListResponse result =
6259
service.getDuplicatePages(
@@ -66,16 +63,11 @@ public void testGetDuplicatePages() {
6663
assertFalse(result.getPages().isEmpty());
6764
assertEquals(TEST_PAGE_HASH, result.getPages().get(0).getHash());
6865

69-
final Set<ComicDetail> comicDetailSet = comicDetailArgumentCaptor.getValue();
70-
assertTrue(comicDetailSet.contains(comicDetail));
71-
7266
final PageRequest pageRequest = pageRequestArgumentCaptor.getValue();
7367
assertEquals(TEST_PAGE_NUMBER, pageRequest.getPageNumber());
7468
assertEquals(TEST_PAGE_SIZE, pageRequest.getPageSize());
7569

7670
Mockito.verify(comicPageRepository, Mockito.times(1)).getDuplicatePages(pageRequest);
77-
Mockito.verify(comicPageRepository, Mockito.times(1)).getPagesWithHash(TEST_PAGE_HASH);
78-
Mockito.verify(duplicatePage, Mockito.times(1)).setComics(comicDetailSet);
7971
}
8072

8173
@Test(expected = DuplicatePageException.class)

comixed-webui/src/app/library/library.fixtures.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,18 @@ import { PAGE_1, PAGE_2, PAGE_3 } from '@app/comic-pages/comic-pages.fixtures';
2626

2727
export const DUPLICATE_PAGE_1: DuplicatePage = {
2828
hash: PAGE_1.hash,
29+
comicCount: 5,
2930
comics: [COMIC_DETAIL_1]
3031
};
3132

3233
export const DUPLICATE_PAGE_2: DuplicatePage = {
3334
hash: PAGE_2.hash,
35+
comicCount: 5,
3436
comics: [COMIC_DETAIL_2]
3537
};
3638

3739
export const DUPLICATE_PAGE_3: DuplicatePage = {
3840
hash: PAGE_3.hash,
41+
comicCount: 5,
3942
comics: [COMIC_DETAIL_3]
4043
};

comixed-webui/src/app/library/models/duplicate-page.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@ import { ComicDetail } from '@app/comic-books/models/comic-detail';
2020

2121
export interface DuplicatePage {
2222
hash: string;
23+
comicCount: number;
2324
comics: ComicDetail[];
2425
}

0 commit comments

Comments
 (0)