Skip to content

Commit 1a4ce9e

Browse files
authored
Merge pull request #74 from Ajou-Hertz/feature/#67-find-instruments
종류별 악기 목록 조회 API 구현
2 parents 867cee6 + 7889142 commit 1a4ce9e

File tree

13 files changed

+1460
-37
lines changed

13 files changed

+1460
-37
lines changed

build.gradle

+22-2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ dependencies {
5050
// Spring Data JPA
5151
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
5252

53+
// Querydsl
54+
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
55+
annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta'
56+
annotationProcessor 'jakarta.annotation:jakarta.annotation-api'
57+
annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
58+
5359
// Spring Validation
5460
implementation 'org.springframework.boot:spring-boot-starter-validation'
5561

@@ -87,6 +93,7 @@ tasks.named('test') {
8793
useJUnitPlatform()
8894
}
8995

96+
// Jacoco
9097
test {
9198
finalizedBy jacocoTestReport
9299
}
@@ -109,7 +116,8 @@ jacocoTestReport {
109116
excludes: [] + Qdomains,
110117
includes: [
111118
'**/service/**',
112-
'**/controller/**'
119+
'**/controller/**',
120+
'**/repository/**'
113121
])
114122
}))
115123
}
@@ -138,8 +146,20 @@ jacocoTestCoverageVerification {
138146

139147
includes = [
140148
'*service.*Service*',
141-
'*controller.*Controller*'
149+
'*controller.*Controller*',
150+
'*repository.*Repository*'
142151
]
143152
}
144153
}
154+
}
155+
156+
// Querydsl
157+
def querydslGeneratedLocation = 'build/generated'
158+
159+
tasks.withType(JavaCompile).configureEach {
160+
options.getGeneratedSourceOutputDirectory().set(file(querydslGeneratedLocation))
161+
}
162+
163+
clean {
164+
delete file(querydslGeneratedLocation)
145165
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.ajou.hertz.common.config;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
6+
import com.querydsl.jpa.impl.JPAQueryFactory;
7+
8+
import jakarta.persistence.EntityManager;
9+
import jakarta.persistence.PersistenceContext;
10+
11+
@Configuration
12+
public class QuerydslConfig {
13+
14+
@PersistenceContext
15+
private EntityManager entityManager;
16+
17+
@Bean
18+
public JPAQueryFactory jpaQueryFactory() {
19+
return new JPAQueryFactory(entityManager);
20+
}
21+
}

src/main/java/com/ajou/hertz/common/config/SecurityConfig.java

+20-11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static org.springframework.http.HttpMethod.*;
44

5+
import java.util.HashMap;
56
import java.util.Map;
67

78
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
@@ -39,17 +40,25 @@ public class SecurityConfig {
3940
"/v3/api-docs/**"
4041
};
4142

42-
private static final Map<String, HttpMethod> AUTH_WHITE_LIST = Map.of(
43-
"/api/auth/login", POST,
44-
"/api/auth/kakao/login", POST,
45-
"/api/users", POST,
46-
"/api/users/existence", GET,
47-
"/api/users/email", GET,
48-
"/api/administrative-areas/sido", GET,
49-
"/api/administrative-areas/sgg", GET,
50-
"/api/administrative-areas/emd", GET,
51-
"/api/instruments", GET
52-
);
43+
private static final Map<String, HttpMethod> AUTH_WHITE_LIST = new HashMap<>();
44+
45+
static {
46+
AUTH_WHITE_LIST.put("/api/auth/login", POST);
47+
AUTH_WHITE_LIST.put("/api/auth/kakao/login", POST);
48+
AUTH_WHITE_LIST.put("/api/users", POST);
49+
AUTH_WHITE_LIST.put("/api/users/existence", GET);
50+
AUTH_WHITE_LIST.put("/api/users/email", GET);
51+
AUTH_WHITE_LIST.put("/api/administrative-areas/sido", GET);
52+
AUTH_WHITE_LIST.put("/api/administrative-areas/sgg", GET);
53+
AUTH_WHITE_LIST.put("/api/administrative-areas/emd", GET);
54+
AUTH_WHITE_LIST.put("/api/instruments", GET);
55+
AUTH_WHITE_LIST.put("/api/instruments/electric-guitars", GET);
56+
AUTH_WHITE_LIST.put("/api/instruments/bass-guitars", GET);
57+
AUTH_WHITE_LIST.put("/api/instruments/acoustic-and-classic-guitars", GET);
58+
AUTH_WHITE_LIST.put("/api/instruments/effectors", GET);
59+
AUTH_WHITE_LIST.put("/api/instruments/amplifiers", GET);
60+
AUTH_WHITE_LIST.put("/api/instruments/audio-equipments", GET);
61+
}
5362

5463
@Bean
5564
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

src/main/java/com/ajou/hertz/domain/instrument/constant/InstrumentSortOption.java

+2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66

77
public enum InstrumentSortOption {
88

9+
CREATED_BY_ASC,
910
CREATED_BY_DESC;
1011

1112
public Sort toSort() {
1213
return switch (this) {
14+
case CREATED_BY_ASC -> Sort.by(ASC, "createdAt");
1315
case CREATED_BY_DESC -> Sort.by(DESC, "createdAt");
1416
};
1517
}

src/main/java/com/ajou/hertz/domain/instrument/controller/InstrumentController.java

+147-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import org.springdoc.core.annotations.ParameterObject;
88
import org.springframework.data.domain.Page;
9-
import org.springframework.data.domain.PageRequest;
109
import org.springframework.http.MediaType;
1110
import org.springframework.http.ResponseEntity;
1211
import org.springframework.security.core.annotation.AuthenticationPrincipal;
@@ -31,6 +30,7 @@
3130
import com.ajou.hertz.domain.instrument.dto.request.CreateNewBassGuitarRequest;
3231
import com.ajou.hertz.domain.instrument.dto.request.CreateNewEffectorRequest;
3332
import com.ajou.hertz.domain.instrument.dto.request.CreateNewElectricGuitarRequest;
33+
import com.ajou.hertz.domain.instrument.dto.request.InstrumentFilterConditions;
3434
import com.ajou.hertz.domain.instrument.dto.response.AcousticAndClassicGuitarResponse;
3535
import com.ajou.hertz.domain.instrument.dto.response.AmplifierResponse;
3636
import com.ajou.hertz.domain.instrument.dto.response.AudioEquipmentResponse;
@@ -62,7 +62,7 @@ public class InstrumentController {
6262
description = "악기 종류와 상관 없이 전체 매물 목록을 조회합니다."
6363
)
6464
@GetMapping(headers = API_VERSION_HEADER_NAME + "=" + 1)
65-
public Page<InstrumentSummaryResponse> findInstruments(
65+
public Page<InstrumentSummaryResponse> findInstrumentsV1(
6666
@Parameter(
6767
description = "페이지 번호. 0부터 시작합니다.",
6868
example = "0"
@@ -76,10 +76,154 @@ public Page<InstrumentSummaryResponse> findInstruments(
7676
) @RequestParam InstrumentSortOption sort
7777
) {
7878
return instrumentQueryService
79-
.findInstruments(PageRequest.of(page, size, sort.toSort()))
79+
.findInstruments(page, size, sort)
8080
.map(InstrumentSummaryResponse::from);
8181
}
8282

83+
@Operation(
84+
summary = "일렉 기타 매물 목록 조회",
85+
description = "일렉 기타 매물 목록을 조회합니다."
86+
)
87+
@GetMapping(value = "/electric-guitars", headers = API_VERSION_HEADER_NAME + "=" + 1)
88+
public Page<ElectricGuitarResponse> findElectricGuitarsV1(
89+
@Parameter(
90+
description = "페이지 번호. 0부터 시작합니다.",
91+
example = "0"
92+
) @RequestParam int page,
93+
@Parameter(
94+
description = "페이지 크기. 한 페이지에 포함될 데이터의 개수를 의미합니다.",
95+
example = "10"
96+
) @RequestParam int size,
97+
@Parameter(
98+
description = "정렬 기준"
99+
) @RequestParam InstrumentSortOption sort,
100+
@ParameterObject @Valid @ModelAttribute InstrumentFilterConditions filterConditions
101+
) {
102+
return instrumentQueryService
103+
.findElectricGuitars(page, size, sort, filterConditions)
104+
.map(ElectricGuitarResponse::from);
105+
}
106+
107+
@Operation(
108+
summary = "베이스 기타 매물 목록 조회",
109+
description = "베이스 기타 매물 목록을 조회합니다."
110+
)
111+
@GetMapping(value = "/bass-guitars", headers = API_VERSION_HEADER_NAME + "=" + 1)
112+
public Page<BassGuitarResponse> findBassGuitarsV1(
113+
@Parameter(
114+
description = "페이지 번호. 0부터 시작합니다.",
115+
example = "0"
116+
) @RequestParam int page,
117+
@Parameter(
118+
description = "페이지 크기. 한 페이지에 포함될 데이터의 개수를 의미합니다.",
119+
example = "10"
120+
) @RequestParam int size,
121+
@Parameter(
122+
description = "정렬 기준"
123+
) @RequestParam InstrumentSortOption sort,
124+
@ParameterObject @Valid @ModelAttribute InstrumentFilterConditions filterConditions
125+
) {
126+
return instrumentQueryService
127+
.findBassGuitars(page, size, sort, filterConditions)
128+
.map(BassGuitarResponse::from);
129+
}
130+
131+
@Operation(
132+
summary = "어쿠스틱&클래식 기타 매물 목록 조회",
133+
description = "어쿠스틱&클래식 기타 매물 목록을 조회합니다."
134+
)
135+
@GetMapping(value = "/acoustic-and-classic-guitars", headers = API_VERSION_HEADER_NAME + "=" + 1)
136+
public Page<AcousticAndClassicGuitarResponse> findAcousticAndClassicGuitarsV1(
137+
@Parameter(
138+
description = "페이지 번호. 0부터 시작합니다.",
139+
example = "0"
140+
) @RequestParam int page,
141+
@Parameter(
142+
description = "페이지 크기. 한 페이지에 포함될 데이터의 개수를 의미합니다.",
143+
example = "10"
144+
) @RequestParam int size,
145+
@Parameter(
146+
description = "정렬 기준"
147+
) @RequestParam InstrumentSortOption sort,
148+
@ParameterObject @Valid @ModelAttribute InstrumentFilterConditions filterConditions
149+
) {
150+
return instrumentQueryService
151+
.findAcousticAndClassicGuitars(page, size, sort, filterConditions)
152+
.map(AcousticAndClassicGuitarResponse::from);
153+
}
154+
155+
@Operation(
156+
summary = "이펙터 매물 목록 조회",
157+
description = "이펙터 매물 목록을 조회합니다."
158+
)
159+
@GetMapping(value = "/effectors", headers = API_VERSION_HEADER_NAME + "=" + 1)
160+
public Page<EffectorResponse> findEffectorsV1(
161+
@Parameter(
162+
description = "페이지 번호. 0부터 시작합니다.",
163+
example = "0"
164+
) @RequestParam int page,
165+
@Parameter(
166+
description = "페이지 크기. 한 페이지에 포함될 데이터의 개수를 의미합니다.",
167+
example = "10"
168+
) @RequestParam int size,
169+
@Parameter(
170+
description = "정렬 기준"
171+
) @RequestParam InstrumentSortOption sort,
172+
@ParameterObject @Valid @ModelAttribute InstrumentFilterConditions filterConditions
173+
) {
174+
return instrumentQueryService
175+
.findEffectors(page, size, sort, filterConditions)
176+
.map(EffectorResponse::from);
177+
}
178+
179+
@Operation(
180+
summary = "앰프 매물 목록 조회",
181+
description = "앰프 매물 목록을 조회합니다."
182+
)
183+
@GetMapping(value = "/amplifiers", headers = API_VERSION_HEADER_NAME + "=" + 1)
184+
public Page<AmplifierResponse> findAmplifiersV1(
185+
@Parameter(
186+
description = "페이지 번호. 0부터 시작합니다.",
187+
example = "0"
188+
) @RequestParam int page,
189+
@Parameter(
190+
description = "페이지 크기. 한 페이지에 포함될 데이터의 개수를 의미합니다.",
191+
example = "10"
192+
) @RequestParam int size,
193+
@Parameter(
194+
description = "정렬 기준"
195+
) @RequestParam InstrumentSortOption sort,
196+
@ParameterObject @Valid @ModelAttribute InstrumentFilterConditions filterConditions
197+
) {
198+
return instrumentQueryService
199+
.findAmplifiers(page, size, sort, filterConditions)
200+
.map(AmplifierResponse::from);
201+
}
202+
203+
@Operation(
204+
summary = "음향 장비 매물 목록 조회",
205+
description = "음향 장비 매물 목록을 조회합니다."
206+
)
207+
@GetMapping(value = "/audio-equipments", headers = API_VERSION_HEADER_NAME + "=" + 1)
208+
public Page<AudioEquipmentResponse> findAudioEquipmentsV1(
209+
@Parameter(
210+
description = "페이지 번호. 0부터 시작합니다.",
211+
example = "0"
212+
) @RequestParam int page,
213+
@Parameter(
214+
description = "페이지 크기. 한 페이지에 포함될 데이터의 개수를 의미합니다.",
215+
example = "10"
216+
) @RequestParam int size,
217+
@Parameter(
218+
description = "정렬 기준"
219+
) @RequestParam InstrumentSortOption sort,
220+
@ParameterObject @Valid @ModelAttribute InstrumentFilterConditions filterConditions
221+
) {
222+
return instrumentQueryService
223+
.findAudioEquipments(page, size, sort, filterConditions)
224+
.map(AudioEquipmentResponse::from);
225+
}
226+
83227
@Operation(
84228
summary = "일렉기타 매물 등록",
85229
description = """
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.ajou.hertz.domain.instrument.dto.request;
2+
3+
import com.ajou.hertz.domain.instrument.constant.InstrumentProgressStatus;
4+
5+
import lombok.AccessLevel;
6+
import lombok.AllArgsConstructor;
7+
import lombok.Getter;
8+
import lombok.NoArgsConstructor;
9+
import lombok.Setter;
10+
11+
@AllArgsConstructor(access = AccessLevel.PRIVATE)
12+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
13+
@Setter // for @ModelAttribute
14+
@Getter
15+
public class InstrumentFilterConditions {
16+
17+
private InstrumentProgressStatus progress;
18+
}

src/main/java/com/ajou/hertz/domain/instrument/repository/InstrumentRepository.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44

55
import com.ajou.hertz.domain.instrument.entity.Instrument;
66

7-
public interface InstrumentRepository extends JpaRepository<Instrument, Long> {
7+
public interface InstrumentRepository extends JpaRepository<Instrument, Long>, InstrumentRepositoryCustom {
88
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.ajou.hertz.domain.instrument.repository;
2+
3+
import org.springframework.data.domain.Page;
4+
5+
import com.ajou.hertz.domain.instrument.constant.InstrumentSortOption;
6+
import com.ajou.hertz.domain.instrument.dto.request.InstrumentFilterConditions;
7+
import com.ajou.hertz.domain.instrument.entity.AcousticAndClassicGuitar;
8+
import com.ajou.hertz.domain.instrument.entity.Amplifier;
9+
import com.ajou.hertz.domain.instrument.entity.AudioEquipment;
10+
import com.ajou.hertz.domain.instrument.entity.BassGuitar;
11+
import com.ajou.hertz.domain.instrument.entity.Effector;
12+
import com.ajou.hertz.domain.instrument.entity.ElectricGuitar;
13+
14+
public interface InstrumentRepositoryCustom {
15+
16+
Page<ElectricGuitar> findElectricGuitars(
17+
int page, int pageSize, InstrumentSortOption sort, InstrumentFilterConditions filterConditions
18+
);
19+
20+
Page<BassGuitar> findBassGuitars(
21+
int page, int pageSize, InstrumentSortOption sort, InstrumentFilterConditions filterConditions
22+
);
23+
24+
Page<AcousticAndClassicGuitar> findAcousticAndClassicGuitars(
25+
int page, int pageSize, InstrumentSortOption sort, InstrumentFilterConditions filterConditions
26+
);
27+
28+
Page<Effector> findEffectors(
29+
int page, int pageSize, InstrumentSortOption sort, InstrumentFilterConditions filterConditions
30+
);
31+
32+
Page<Amplifier> findAmplifiers(
33+
int page, int pageSize, InstrumentSortOption sort, InstrumentFilterConditions filterConditions
34+
);
35+
36+
Page<AudioEquipment> findAudioEquipments(
37+
int page, int pageSize, InstrumentSortOption sort, InstrumentFilterConditions filterConditions
38+
);
39+
}

0 commit comments

Comments
 (0)