Conversation
WalkthroughThis update introduces a new school registration feature, including a POST endpoint, DTO, and service logic. It refactors repository usage by removing Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant SchoolController
participant SchoolService
participant SchoolJpaRepository
Client->>SchoolController: POST /school (SchoolRegistrationRequest)
SchoolController->>SchoolService: registerSchool(request)
SchoolService->>SchoolRegistrationRequest: toEntity()
SchoolService->>SchoolJpaRepository: save(SchoolJpaEntity)
SchoolJpaRepository-->>SchoolService: (persisted entity)
SchoolService-->>SchoolController: void
SchoolController-->>Client: 201 Created (ApiResponseWrapper)
Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Summary of Changes
Hello @wlgns12370, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request introduces the core functionality for administrators to register new schools within the system. It encompasses the full stack from a new API endpoint and request DTO to the service layer logic for data persistence, including updates to the SchoolJpaEntity for easier creation. Furthermore, it adds an initializer to populate initial school data and includes a minor repository refactoring along with a new query for school application statistics.
Highlights
- New School Registration API: I've implemented a new API endpoint (
POST /schools) inSchoolController.javathat allows administrators to register new schools. This endpoint accepts aSchoolRegistrationRequestin the request body. - School Registration Service Logic: The
SchoolService.javanow includes aregisterSchool()method. This method handles the business logic for persisting newSchoolJpaEntityinstances based on the provided registration request, ensuring proper data storage. - New School Registration DTO: A new DTO,
SchoolRegistrationRequest.java, has been introduced. This record defines the structure for incoming school registration data, including validation annotations forschoolName,area,address,examDate, andcapacity, and provides atoEntity()method for conversion to aSchoolJpaEntity. - Initial School Data Population: A new
SchoolInitializer.javacomponent has been added. This component uses a@PostConstructmethod to pre-populate the database with dummy school data if no schools are present, which is beneficial for development and testing environments. - Entity Builder Pattern Adoption: The
SchoolJpaEntity.javahas been updated with Lombok's@Builderannotation on both the class and its constructor. This facilitates a more readable and flexible way to constructSchoolJpaEntityinstances, as seen in the newSchoolRegistrationRequest.toEntity()method andSchoolInitializer. - Repository Refactoring and New Query: In
SchoolQuotaCacheManager.java,SchoolRepositoryhas been consistently renamed toSchoolJpaRepository. Additionally,SchoolJpaRepository.javanow includes a new custom JPQL query,countBySchoolNameGroupBy(), designed to retrieve school application counts, which could be used for reporting or dashboard features.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Code Review
This pull request introduces a school registration feature. Key improvements include adding request validation in the controller, using the Area enum in the request DTO, preventing duplicate school registrations, and restricting the data initializer to non-production environments. These changes will enhance the reliability and data integrity of the new feature.
|
|
||
| @PostMapping | ||
| public ResponseEntity<ApiResponseWrapper<Void>> create( | ||
| @RequestBody SchoolRegistrationRequest request |
| public void registerSchool(SchoolRegistrationRequest request) { | ||
| schoolJpaRepository.save(request.toEntity()); | ||
| } |
There was a problem hiding this comment.
Consider checking for an existing school with the same name, area, and exam date before saving to prevent duplicate entries and maintain data integrity.
public void registerSchool(SchoolRegistrationRequest request) {
if (schoolJpaRepository.findBySchoolNameAndAreaAndExamDate(request.schoolName(), Area.valueOf(request.area()), request.examDate()).isPresent()) {
throw new IllegalArgumentException("A school with the same name, area, and exam date already exists.");
}
schoolJpaRepository.save(request.toEntity());
}| package life.mosu.mosuserver.global.initializer; | ||
|
|
||
| import static life.mosu.mosuserver.domain.school.Area.DAECHI; | ||
| import static life.mosu.mosuserver.domain.school.Area.NOWON; | ||
|
|
||
| import jakarta.annotation.PostConstruct; | ||
| import java.time.LocalDate; | ||
| import life.mosu.mosuserver.domain.school.AddressJpaVO; | ||
| import life.mosu.mosuserver.domain.school.SchoolJpaEntity; | ||
| import life.mosu.mosuserver.domain.school.SchoolJpaRepository; | ||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| @Slf4j | ||
| @Component | ||
| @RequiredArgsConstructor | ||
| public class SchoolInitializer { | ||
|
|
||
| private final SchoolJpaRepository schoolRepository; | ||
|
|
||
| @PostConstruct | ||
| public void init() { | ||
| if (schoolRepository.count() > 0) { | ||
| log.info("이미 학교 더미 데이터가 존재하여 초기화를 건너뜁니다."); | ||
| return; | ||
| } | ||
|
|
||
| SchoolJpaEntity school1 = SchoolJpaEntity.builder() | ||
| .schoolName("모수고등학교") | ||
| .area(DAECHI) | ||
| .address(new AddressJpaVO("06164", "서울특별시", "강남구 테헤란로 123")) | ||
| .examDate(LocalDate.of(2025, 11, 20)) | ||
| .capacity(300L) | ||
| .build(); | ||
| schoolRepository.save(school1); | ||
|
|
||
| SchoolJpaEntity school2 = SchoolJpaEntity.builder() | ||
| .schoolName("대치고등학교") | ||
| .area(DAECHI) | ||
| .address(new AddressJpaVO("06283", "서울특별시", "강남구 대치동 학원가 100")) | ||
| .examDate(LocalDate.of(2025, 12, 5)) | ||
| .capacity(150L) | ||
| .build(); | ||
| schoolRepository.save(school2); | ||
|
|
||
| SchoolJpaEntity school3 = SchoolJpaEntity.builder() | ||
| .schoolName("부산명문고") | ||
| .area(DAECHI) | ||
| .address(new AddressJpaVO("48057", "부산광역시", "해운대구 센텀시티로 50")) | ||
| .examDate(LocalDate.of(2025, 11, 25)) | ||
| .capacity(250L) | ||
| .build(); | ||
| schoolRepository.save(school3); | ||
|
|
||
| SchoolJpaEntity school4 = SchoolJpaEntity.builder() | ||
| .schoolName("노원스터디센터") | ||
| .area(NOWON) | ||
| .address(new AddressJpaVO("01777", "서울특별시", "노원구 동일로 1400")) | ||
| .examDate(LocalDate.of(2026, 1, 10)) | ||
| .capacity(80L) | ||
| .build(); | ||
| schoolRepository.save(school4); | ||
| } | ||
| } No newline at end of file |
|
|
||
| @Schema(description = "지역 (예: DAECHI, MOKDONG, NOWON)", example = "DAECHI") | ||
| @NotNull(message = "지역은 필수 입니다.") | ||
| String area, |
| SchoolJpaEntity school1 = SchoolJpaEntity.builder() | ||
| .schoolName("모수고등학교") | ||
| .area(DAECHI) | ||
| .address(new AddressJpaVO("06164", "서울특별시", "강남구 테헤란로 123")) | ||
| .examDate(LocalDate.of(2025, 11, 20)) | ||
| .capacity(300L) | ||
| .build(); | ||
| schoolRepository.save(school1); | ||
|
|
||
| SchoolJpaEntity school2 = SchoolJpaEntity.builder() | ||
| .schoolName("대치고등학교") | ||
| .area(DAECHI) | ||
| .address(new AddressJpaVO("06283", "서울특별시", "강남구 대치동 학원가 100")) | ||
| .examDate(LocalDate.of(2025, 12, 5)) | ||
| .capacity(150L) | ||
| .build(); | ||
| schoolRepository.save(school2); | ||
|
|
||
| SchoolJpaEntity school3 = SchoolJpaEntity.builder() | ||
| .schoolName("부산명문고") | ||
| .area(DAECHI) | ||
| .address(new AddressJpaVO("48057", "부산광역시", "해운대구 센텀시티로 50")) | ||
| .examDate(LocalDate.of(2025, 11, 25)) | ||
| .capacity(250L) | ||
| .build(); | ||
| schoolRepository.save(school3); | ||
|
|
||
| SchoolJpaEntity school4 = SchoolJpaEntity.builder() | ||
| .schoolName("노원스터디센터") | ||
| .area(NOWON) | ||
| .address(new AddressJpaVO("01777", "서울특별시", "노원구 동일로 1400")) | ||
| .examDate(LocalDate.of(2026, 1, 10)) | ||
| .capacity(80L) | ||
| .build(); | ||
| schoolRepository.save(school4); | ||
| } |
There was a problem hiding this comment.
Use saveAll() to persist the school entities in a single batch operation for better efficiency.
List<SchoolJpaEntity> schools = List.of(
SchoolJpaEntity.builder()
.schoolName("모수고등학교")
.area(DAECHI)
.address(new AddressJpaVO("06164", "서울특별시", "강남구 테헤란로 123"))
.examDate(LocalDate.of(2025, 11, 20))
.capacity(300L)
.build(),
SchoolJpaEntity.builder()
.schoolName("대치고등학교")
.area(DAECHI)
.address(new AddressJpaVO("06283", "서울특별시", "강남구 대치동 학원가 100"))
.examDate(LocalDate.of(2025, 12, 5))
.capacity(150L)
.build(),
SchoolJpaEntity.builder()
.schoolName("부산명문고")
.area(DAECHI)
.address(new AddressJpaVO("48057", "부산광역시", "해운대구 센텀시티로 50"))
.examDate(LocalDate.of(2025, 11, 25))
.capacity(250L)
.build(),
SchoolJpaEntity.builder()
.schoolName("노원스터디센터")
.area(NOWON)
.address(new AddressJpaVO("01777", "서울특별시", "노원구 동일로 1400"))
.examDate(LocalDate.of(2026, 1, 10))
.capacity(80L)
.build()
);
schoolRepository.saveAll(schools);There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
src/main/java/life/mosu/mosuserver/presentation/school/SchoolController.java (1)
24-31: Consider adding validation annotation for request body.The POST endpoint implementation follows REST conventions well. However, consider adding
@Validannotation to the request parameter to ensure proper validation of theSchoolRegistrationRequestDTO.@PostMapping public ResponseEntity<ApiResponseWrapper<Void>> create( - @RequestBody SchoolRegistrationRequest request + @RequestBody @Valid SchoolRegistrationRequest request ) {Don't forget to add the import:
+import jakarta.validation.Valid;src/main/java/life/mosu/mosuserver/application/school/SchoolService.java (1)
27-30: Consider adding validation and return value for school registration.The
registerSchoolmethod implementation is straightforward but could be enhanced:
- Validation: Consider checking for duplicate schools before saving
- Return value: Consider returning the created school ID or entity for confirmation
- Error handling: Database constraint violations should be properly handled
@Transactional -public void registerSchool(SchoolRegistrationRequest request) { - schoolJpaRepository.save(request.toEntity()); +public SchoolJpaEntity registerSchool(SchoolRegistrationRequest request) { + // Optional: Add duplicate check + // if (schoolJpaRepository.findBySchoolNameAndAreaAndExamDate(...).isPresent()) { + // throw new IllegalArgumentException("School already exists"); + // } + return schoolJpaRepository.save(request.toEntity()); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
src/main/java/life/mosu/mosuserver/application/school/SchoolQuotaCacheManager.java(2 hunks)src/main/java/life/mosu/mosuserver/application/school/SchoolService.java(2 hunks)src/main/java/life/mosu/mosuserver/domain/school/SchoolJpaEntity.java(2 hunks)src/main/java/life/mosu/mosuserver/domain/school/SchoolJpaRepository.java(1 hunks)src/main/java/life/mosu/mosuserver/domain/school/SchoolRepository.java(0 hunks)src/main/java/life/mosu/mosuserver/global/initializer/SchoolInitializer.java(1 hunks)src/main/java/life/mosu/mosuserver/presentation/school/SchoolController.java(2 hunks)src/main/java/life/mosu/mosuserver/presentation/school/dto/SchoolRegistrationRequest.java(1 hunks)
💤 Files with no reviewable changes (1)
- src/main/java/life/mosu/mosuserver/domain/school/SchoolRepository.java
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/java/life/mosu/mosuserver/global/initializer/SchoolInitializer.java (1)
src/main/java/life/mosu/mosuserver/global/runner/ApplicationSchoolPreWarmRunner.java (1)
RequiredArgsConstructor(9-19)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build-and-deploy
🔇 Additional comments (6)
src/main/java/life/mosu/mosuserver/domain/school/SchoolJpaEntity.java (1)
45-45: LGTM! Builder pattern implementation is well-placed.The
@Builderannotation on the constructor enables flexible entity creation, which aligns well with the new school registration functionality where DTOs need to convert to entities.src/main/java/life/mosu/mosuserver/application/school/SchoolQuotaCacheManager.java (1)
6-6: LGTM! Repository interface refactoring is consistent.The migration from
SchoolRepositorytoSchoolJpaRepositoryis properly implemented with both import and field declaration updated accordingly.Also applies to: 19-19
src/main/java/life/mosu/mosuserver/domain/school/SchoolJpaRepository.java (1)
11-17: LGTM! Well-structured JPQL query implementation.The
countBySchoolNameGroupBy()method is properly implemented with:
- Correct LEFT JOIN to include schools without applications
- Proper GROUP BY clause including both ID and name
- Appropriate projection mapping to
SchoolApplicationProjectionsrc/main/java/life/mosu/mosuserver/application/school/SchoolService.java (1)
19-19: LGTM! Improved transactional annotation granularity.Moving from class-level to method-level
@Transactionalannotations provides better control over transaction boundaries and makes the read-only nature ofgetSchools()explicit.src/main/java/life/mosu/mosuserver/global/initializer/SchoolInitializer.java (1)
22-27: LGTM! Good defensive programming practice.The conditional check prevents duplicate initialization when the application restarts, which is a solid defensive programming approach.
src/main/java/life/mosu/mosuserver/presentation/school/dto/SchoolRegistrationRequest.java (1)
14-36: LGTM! Comprehensive validation and documentation.The record definition includes appropriate validation annotations and detailed Swagger documentation, providing good API contract definition.
| SchoolJpaEntity school3 = SchoolJpaEntity.builder() | ||
| .schoolName("부산명문고") | ||
| .area(DAECHI) | ||
| .address(new AddressJpaVO("48057", "부산광역시", "해운대구 센텀시티로 50")) | ||
| .examDate(LocalDate.of(2025, 11, 25)) | ||
| .capacity(250L) | ||
| .build(); | ||
| schoolRepository.save(school3); |
There was a problem hiding this comment.
Fix logical inconsistency in school location data.
The school "부산명문고" (Busan school) has an address in Busan ("부산광역시 해운대구") but is assigned to the DAECHI area, which is inconsistent.
Apply this diff to fix the area assignment:
- SchoolJpaEntity school3 = SchoolJpaEntity.builder()
- .schoolName("부산명문고")
- .area(DAECHI)
- .address(new AddressJpaVO("48057", "부산광역시", "해운대구 센텀시티로 50"))
- .examDate(LocalDate.of(2025, 11, 25))
- .capacity(250L)
- .build();
+ SchoolJpaEntity school3 = SchoolJpaEntity.builder()
+ .schoolName("부산명문고")
+ .area(BUSAN) // or create appropriate enum value
+ .address(new AddressJpaVO("48057", "부산광역시", "해운대구 센텀시티로 50"))
+ .examDate(LocalDate.of(2025, 11, 25))
+ .capacity(250L)
+ .build();📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| SchoolJpaEntity school3 = SchoolJpaEntity.builder() | |
| .schoolName("부산명문고") | |
| .area(DAECHI) | |
| .address(new AddressJpaVO("48057", "부산광역시", "해운대구 센텀시티로 50")) | |
| .examDate(LocalDate.of(2025, 11, 25)) | |
| .capacity(250L) | |
| .build(); | |
| schoolRepository.save(school3); | |
| SchoolJpaEntity school3 = SchoolJpaEntity.builder() | |
| .schoolName("부산명문고") | |
| .area(BUSAN) | |
| .address(new AddressJpaVO("48057", "부산광역시", "해운대구 센텀시티로 50")) | |
| .examDate(LocalDate.of(2025, 11, 25)) | |
| .capacity(250L) | |
| .build(); | |
| schoolRepository.save(school3); |
🤖 Prompt for AI Agents
In src/main/java/life/mosu/mosuserver/global/initializer/SchoolInitializer.java
around lines 47 to 54, the school "부산명문고" has an address in Busan but is
incorrectly assigned to the DAECHI area. Change the area assignment from DAECHI
to the correct Busan-related area constant to ensure consistency between the
area and address fields.
| @PostConstruct | ||
| public void init() { | ||
| if (schoolRepository.count() > 0) { | ||
| log.info("이미 학교 더미 데이터가 존재하여 초기화를 건너뜁니다."); | ||
| return; | ||
| } | ||
|
|
||
| SchoolJpaEntity school1 = SchoolJpaEntity.builder() | ||
| .schoolName("모수고등학교") | ||
| .area(DAECHI) | ||
| .address(new AddressJpaVO("06164", "서울특별시", "강남구 테헤란로 123")) | ||
| .examDate(LocalDate.of(2025, 11, 20)) | ||
| .capacity(300L) | ||
| .build(); | ||
| schoolRepository.save(school1); | ||
|
|
||
| SchoolJpaEntity school2 = SchoolJpaEntity.builder() | ||
| .schoolName("대치고등학교") | ||
| .area(DAECHI) | ||
| .address(new AddressJpaVO("06283", "서울특별시", "강남구 대치동 학원가 100")) | ||
| .examDate(LocalDate.of(2025, 12, 5)) | ||
| .capacity(150L) | ||
| .build(); | ||
| schoolRepository.save(school2); | ||
|
|
||
| SchoolJpaEntity school3 = SchoolJpaEntity.builder() | ||
| .schoolName("부산명문고") | ||
| .area(DAECHI) | ||
| .address(new AddressJpaVO("48057", "부산광역시", "해운대구 센텀시티로 50")) | ||
| .examDate(LocalDate.of(2025, 11, 25)) | ||
| .capacity(250L) | ||
| .build(); | ||
| schoolRepository.save(school3); | ||
|
|
||
| SchoolJpaEntity school4 = SchoolJpaEntity.builder() | ||
| .schoolName("노원스터디센터") | ||
| .area(NOWON) | ||
| .address(new AddressJpaVO("01777", "서울특별시", "노원구 동일로 1400")) | ||
| .examDate(LocalDate.of(2026, 1, 10)) | ||
| .capacity(80L) | ||
| .build(); | ||
| schoolRepository.save(school4); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Consider adding transaction management for data consistency.
The initialization method performs multiple repository saves without explicit transaction management, which could lead to partial data if an error occurs during initialization.
Consider adding @Transactional annotation:
+import org.springframework.transaction.annotation.Transactional;
@PostConstruct
+@Transactional
public void init() {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @PostConstruct | |
| public void init() { | |
| if (schoolRepository.count() > 0) { | |
| log.info("이미 학교 더미 데이터가 존재하여 초기화를 건너뜁니다."); | |
| return; | |
| } | |
| SchoolJpaEntity school1 = SchoolJpaEntity.builder() | |
| .schoolName("모수고등학교") | |
| .area(DAECHI) | |
| .address(new AddressJpaVO("06164", "서울특별시", "강남구 테헤란로 123")) | |
| .examDate(LocalDate.of(2025, 11, 20)) | |
| .capacity(300L) | |
| .build(); | |
| schoolRepository.save(school1); | |
| SchoolJpaEntity school2 = SchoolJpaEntity.builder() | |
| .schoolName("대치고등학교") | |
| .area(DAECHI) | |
| .address(new AddressJpaVO("06283", "서울특별시", "강남구 대치동 학원가 100")) | |
| .examDate(LocalDate.of(2025, 12, 5)) | |
| .capacity(150L) | |
| .build(); | |
| schoolRepository.save(school2); | |
| SchoolJpaEntity school3 = SchoolJpaEntity.builder() | |
| .schoolName("부산명문고") | |
| .area(DAECHI) | |
| .address(new AddressJpaVO("48057", "부산광역시", "해운대구 센텀시티로 50")) | |
| .examDate(LocalDate.of(2025, 11, 25)) | |
| .capacity(250L) | |
| .build(); | |
| schoolRepository.save(school3); | |
| SchoolJpaEntity school4 = SchoolJpaEntity.builder() | |
| .schoolName("노원스터디센터") | |
| .area(NOWON) | |
| .address(new AddressJpaVO("01777", "서울특별시", "노원구 동일로 1400")) | |
| .examDate(LocalDate.of(2026, 1, 10)) | |
| .capacity(80L) | |
| .build(); | |
| schoolRepository.save(school4); | |
| } | |
| // at the top of the file, among your other imports: | |
| import org.springframework.transaction.annotation.Transactional; | |
| @PostConstruct | |
| @Transactional | |
| public void init() { | |
| if (schoolRepository.count() > 0) { | |
| log.info("이미 학교 더미 데이터가 존재하여 초기화를 건너뜁니다."); | |
| return; | |
| } | |
| SchoolJpaEntity school1 = SchoolJpaEntity.builder() | |
| .schoolName("모수고등학교") | |
| .area(DAECHI) | |
| .address(new AddressJpaVO("06164", "서울특별시", "강남구 테헤란로 123")) | |
| .examDate(LocalDate.of(2025, 11, 20)) | |
| .capacity(300L) | |
| .build(); | |
| schoolRepository.save(school1); | |
| SchoolJpaEntity school2 = SchoolJpaEntity.builder() | |
| .schoolName("대치고등학교") | |
| .area(DAECHI) | |
| .address(new AddressJpaVO("06283", "서울특별시", "강남구 대치동 학원가 100")) | |
| .examDate(LocalDate.of(2025, 12, 5)) | |
| .capacity(150L) | |
| .build(); | |
| schoolRepository.save(school2); | |
| SchoolJpaEntity school3 = SchoolJpaEntity.builder() | |
| .schoolName("부산명문고") | |
| .area(DAECHI) | |
| .address(new AddressJpaVO("48057", "부산광역시", "해운대구 센텀시티로 50")) | |
| .examDate(LocalDate.of(2025, 11, 25)) | |
| .capacity(250L) | |
| .build(); | |
| schoolRepository.save(school3); | |
| SchoolJpaEntity school4 = SchoolJpaEntity.builder() | |
| .schoolName("노원스터디센터") | |
| .area(NOWON) | |
| .address(new AddressJpaVO("01777", "서울특별시", "노원구 동일로 1400")) | |
| .examDate(LocalDate.of(2026, 1, 10)) | |
| .capacity(80L) | |
| .build(); | |
| schoolRepository.save(school4); | |
| } |
🤖 Prompt for AI Agents
In src/main/java/life/mosu/mosuserver/global/initializer/SchoolInitializer.java
around lines 22 to 64, the init method performs multiple save operations without
transaction management, risking partial data persistence if an error occurs. Add
the @Transactional annotation to the init method to ensure all save operations
are executed within a single transaction, maintaining data consistency by
rolling back all changes if any save fails.
| @Schema(description = "지역 (예: DAECHI, MOKDONG, NOWON)", example = "DAECHI") | ||
| @NotNull(message = "지역은 필수 입니다.") | ||
| String area, |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Add validation for area enum values.
The area field accepts any String but gets converted to an enum using valueOf(), which can throw IllegalArgumentException for invalid values.
Consider adding custom validation:
+import jakarta.validation.constraints.Pattern;
@Schema(description = "지역 (예: DAECHI, MOKDONG, NOWON)", example = "DAECHI")
@NotNull(message = "지역은 필수 입니다.")
+@Pattern(regexp = "DAECHI|MOKDONG|NOWON", message = "지역은 DAECHI, MOKDONG, NOWON 중 하나여야 합니다.")
String area,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @Schema(description = "지역 (예: DAECHI, MOKDONG, NOWON)", example = "DAECHI") | |
| @NotNull(message = "지역은 필수 입니다.") | |
| String area, | |
| // add this import alongside the other jakarta.validation imports | |
| import jakarta.validation.constraints.Pattern; | |
| @Schema(description = "지역 (예: DAECHI, MOKDONG, NOWON)", example = "DAECHI") | |
| @NotNull(message = "지역은 필수 입니다.") | |
| @Pattern(regexp = "DAECHI|MOKDONG|NOWON", message = "지역은 DAECHI, MOKDONG, NOWON 중 하나여야 합니다.") | |
| String area, |
🤖 Prompt for AI Agents
In
src/main/java/life/mosu/mosuserver/presentation/school/dto/SchoolRegistrationRequest.java
around lines 20 to 22, the area field is a String that is later converted to an
enum using valueOf(), which can throw an exception if the value is invalid. To
fix this, add a custom validator annotation to the area field that checks if the
String matches one of the allowed enum values before conversion. Implement a
validator class that validates the input against the enum constants and apply
this annotation to the area field to ensure only valid enum values are accepted.
| public SchoolJpaEntity toEntity() { | ||
| AddressJpaVO address = address().toValueObject(); | ||
| return SchoolJpaEntity.builder() | ||
| .schoolName(schoolName) | ||
| .area(Area.valueOf(area)) | ||
| .address(address) | ||
| .examDate(examDate) | ||
| .capacity(capacity) | ||
| .build(); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Fix variable name shadowing in toEntity() method.
The local variable address shadows the record field address(), which can lead to confusion and potential bugs.
Apply this diff to use a distinct variable name:
public SchoolJpaEntity toEntity() {
- AddressJpaVO address = address().toValueObject();
+ AddressJpaVO addressVO = address().toValueObject();
return SchoolJpaEntity.builder()
.schoolName(schoolName)
.area(Area.valueOf(area))
- .address(address)
+ .address(addressVO)
.examDate(examDate)
.capacity(capacity)
.build();
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public SchoolJpaEntity toEntity() { | |
| AddressJpaVO address = address().toValueObject(); | |
| return SchoolJpaEntity.builder() | |
| .schoolName(schoolName) | |
| .area(Area.valueOf(area)) | |
| .address(address) | |
| .examDate(examDate) | |
| .capacity(capacity) | |
| .build(); | |
| } | |
| public SchoolJpaEntity toEntity() { | |
| AddressJpaVO addressVO = address().toValueObject(); | |
| return SchoolJpaEntity.builder() | |
| .schoolName(schoolName) | |
| .area(Area.valueOf(area)) | |
| .address(addressVO) | |
| .examDate(examDate) | |
| .capacity(capacity) | |
| .build(); | |
| } |
🤖 Prompt for AI Agents
In
src/main/java/life/mosu/mosuserver/presentation/school/dto/SchoolRegistrationRequest.java
between lines 38 and 47, the local variable named 'address' in the toEntity()
method shadows the record field 'address()', causing confusion. Rename the local
variable to a distinct name such as 'addressVO' to clearly differentiate it from
the record field and avoid shadowing issues.
✨ 구현한 기능
📢 논의하고 싶은 내용
🎸 기타
Summary by CodeRabbit