Skip to content

MOSU-276 feat: flyway DB 마이그레이션#296

Merged
wlgns12370 merged 12 commits intodevelopfrom
feature/mosu-276
Aug 11, 2025
Merged

MOSU-276 feat: flyway DB 마이그레이션#296
wlgns12370 merged 12 commits intodevelopfrom
feature/mosu-276

Conversation

@wlgns12370
Copy link
Contributor

@wlgns12370 wlgns12370 commented Aug 10, 2025

✨ 구현한 기능

📢 논의하고 싶은 내용

  • x

🎸 기타

  • 학교 주소를 바꿔야합니다.
  • 해당 pr은 천천히 병합할 예정이어서 update lunch option text to "도시락 X" 해당 커밋은 develop에 따로 커밋해두겠습니다.

Summary by CodeRabbit

  • Refactor

    • Removed all form-related APIs and DTOs.
    • Dropped terms/privacy consent fields from user accounts.
    • Made phone numbers unique for users.
    • Switched file key fields to support longer text.
  • Chores

    • Enabled Flyway migrations and changed schema management to validate.
    • Added initial database schema (V1) and seed data (V2) for exams, events, notices, and FAQs.
    • Updated seed data to include richer content and attachments.

@coderabbitai
Copy link

coderabbitai bot commented Aug 10, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Caution

Review failed

The pull request is closed.

Walkthrough

Removed all form-related classes and DTOs. Modified user entity to drop agreement flags and set phoneNumber unique. Adjusted OAuth and signup flows to omit agreement flags. Changed s3Key columns to TEXT. Enabled Flyway, switched Hibernate ddl-auto to validate, and added V1/V2 migration scripts with seed data; updated data.sql.

Changes

Cohort / File(s) Summary of Changes
Form module removal
src/main/java/life/mosu/mosuserver/application/form/FormService.java, .../domain/form/FormJpaEntity.java, .../domain/form/FormJpaRepository.java, .../presentation/form/FormController.java, .../presentation/form/FormControllerDocs.java, .../presentation/form/dto/FormListResponse.java, .../presentation/form/dto/FormResponse.java, .../presentation/form/dto/RegisterFormRequest.java
Deleted form service, controller, repository, entity, and DTOs.
User agreement fields removal and related builders
src/main/java/life/mosu/mosuserver/domain/user/entity/UserJpaEntity.java, .../application/oauth/OAuthUserPersistenceProcessor.java, .../presentation/application/dto/ApplicationGuestRequest.java, .../presentation/auth/dto/request/SignUpAccountRequest.java
Removed agreedToTermsOfService/agreedToPrivacyPolicy fields from User; updated builders to stop setting them; made phoneNumber unique.
File s3Key column definition
src/main/java/life/mosu/mosuserver/domain/file/FileMoveFailLog.java, .../domain/file/FileWithTime.java
Set s3Key column to TEXT via @column(columnDefinition = "TEXT").
Database migrations and config
src/main/resources/application-base.yml, .../db/migration/V1__init.sql, .../db/migration/V2__insert_data.sql, .../db/data/data.sql
Enabled Flyway, set ddl-auto to validate; added initial schema and seed migrations; updated seed data SQL.

Sequence Diagram(s)

sequenceDiagram
    participant App as Application
    participant Flyway as Flyway
    participant DB as Database

    App->>Flyway: Start-up
    Flyway->>DB: Apply V1__init.sql
    Flyway->>DB: Apply V2__insert_data.sql
    Flyway-->>App: Migration complete
    App->>DB: Run with ddl-auto=validate
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Assessment against linked issues

Objective Addressed Explanation
Flyway DB migration setup and initial migrations (#276)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Remove form feature (service, controller, repository, entity, DTOs) (.../form/*.java) The issue only requests Flyway migration; removing the form module is unrelated.
Remove agreement fields from User and enforce unique phoneNumber (domain/user/entity/UserJpaEntity.java) Changing domain model and constraints goes beyond Flyway setup.
Stop setting agreement flags in OAuth and signup builders (application/oauth/OAuthUserPersistenceProcessor.java, presentation/.../ApplicationGuestRequest.java, presentation/.../SignUpAccountRequest.java) Behavior changes in user creation are not part of Flyway migration.
Change s3Key column to TEXT (domain/file/FileMoveFailLog.java, domain/file/FileWithTime.java) Entity column definition changes are outside the migration setup objective.

Possibly related PRs

Suggested labels

우선순위 중

Suggested reviewers

  • chominju02

Poem

I hop through schemas, ears held high,
Flyway flutters across the sky.
Forms have vanished, fields made neat,
TEXTy keys for tasty treats.
Unique rings on phones now chime—
Migration done, right on time. 🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7fe1691 and ed6a583.

📒 Files selected for processing (2)
  • src/main/resources/application-base.yml (1 hunks)
  • src/main/resources/db/migration/V2__insert_data.sql (1 hunks)
✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/mosu-276

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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!

I've implemented a significant update to our database management system by integrating Flyway for version-controlled schema migrations. This change establishes a robust framework for evolving our database schema reliably. Concurrently, I've removed the 'Form' feature, which was no longer necessary, and simplified user agreement fields across the application. Additionally, I've made minor adjustments to text displays and database column definitions to improve data handling and clarity.

Highlights

  • Database Migration with Flyway: I've integrated Flyway for database schema management. This involves adding an initial schema script (V1__init.sql) and configuring Spring Boot to use ddl-auto: validate and sql.init.mode: always to ensure that database changes are applied and validated through Flyway.
  • Removal of 'Form' Feature: I've removed the entire 'Form' feature, including its service, JPA entity, repository, controller, and related DTOs. This indicates that the functionality previously handled by these components is no longer needed or has been refactored elsewhere.
  • User Agreement Field Simplification: I've streamlined user agreement handling by removing the agreedToTermsOfService and agreedToPrivacyPolicy fields from the UserJpaEntity and related DTOs/processors. This simplifies the user registration and OAuth processes.
  • Lunch Option Text Update: I've updated the Lunch enum and its usage in ExamApplicationService to change the display text for 'no lunch selected' from '신청 안 함' to '도시락 X', providing a more direct translation.
  • Database Column Type Adjustment: I've modified the s3Key columns in FileMoveFailLog and FileWithTime entities to use TEXT column definition, allowing for longer S3 key strings to be stored without truncation.
  • Initial Data Population Update: I've updated the data.sql script to include new initial data for events, notices, and FAQs, and also adjusted existing exam data, ensuring the database is populated with relevant information upon initialization.
  • Phone Number Uniqueness Constraint: I've added a unique constraint to the phoneNumber column in the UserJpaEntity, ensuring that each user has a distinct phone number in the system.
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 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 or fill out our survey 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

  1. 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.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request successfully introduces Flyway for database migrations, which is a great improvement for managing schema changes. The configuration change from ddl-auto: update to validate is correct.

My review includes several points for improvement:

  • A critical issue with the data seeding strategy (spring.sql.init.mode: always) that could cause application startup failures.
  • A high-severity database design issue regarding data duplication between the user and profile tables.
  • A few medium-severity suggestions to improve maintainability and data quality, such as avoiding hardcoded strings, fixing incorrect seed data, and adjusting a column size for future flexibility.

Please review the detailed comments. Addressing these points will improve the robustness and maintainability of the application.

Comment on lines +257 to +276
CREATE TABLE profile
(
deleted BIT(1) NOT NULL,
profile_id BIGINT AUTO_INCREMENT NOT NULL,
created_at datetime NULL,
updated_at datetime NULL,
user_id BIGINT NOT NULL,
user_name VARCHAR(255) NOT NULL,
gender VARCHAR(255) NOT NULL,
birth date NOT NULL,
phone_number VARCHAR(255) NOT NULL,
email VARCHAR(255) NULL,
education VARCHAR(255) NULL,
recommender_phone_number VARCHAR(255) NULL,
grade VARCHAR(255) NULL,
school_name VARCHAR(255) NULL,
zipcode VARCHAR(255) NULL,
street VARCHAR(255) NULL,
CONSTRAINT pk_profile PRIMARY KEY (profile_id)
);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The profile table duplicates several columns from the user table (user_name, gender, birth, phone_number). This data redundancy can lead to inconsistencies and maintenance issues. For example, if a user's phone number changes, it would need to be updated in both tables.

Consider refactoring the schema to avoid this duplication. Two common approaches are:

  1. Merge the profile specific columns (email, education, etc.) into the user table. This is simpler if a profile is always present for a user.
  2. Remove the duplicated columns from the profile table, and only keep the user_id as a foreign key to the user table. The application would then join the tables to retrieve the full user profile information.

This change would improve the database design and make the application more robust.

AddressResponse.from(examApplicationInfo.address()),
subjects,
examApplicationInfo.isLunchChecked() ? examApplicationInfo.lunchName() : "신청 안 함",
examApplicationInfo.isLunchChecked() ? examApplicationInfo.lunchName() : "도시락 X",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The string "도시락 X" is hardcoded here. This value is also defined in the Lunch enum as NONE("도시락 X"). To improve maintainability and avoid potential inconsistencies if the text ever changes, it's better to use the value from the enum. You can import life.mosu.mosuserver.domain.application.entity.Lunch and use Lunch.NONE.getLunchName().

Suggested change
examApplicationInfo.isLunchChecked() ? examApplicationInfo.lunchName() : "도시락 X",
examApplicationInfo.isLunchChecked() ? examApplicationInfo.lunchName() : life.mosu.mosuserver.domain.application.entity.Lunch.NONE.getLunchName(),

created_at datetime NULL,
updated_at datetime NULL,
question VARCHAR(500) NOT NULL,
answer VARCHAR(255) NOT NULL,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The answer column in the faq table is defined as VARCHAR(255). While the current seed data fits, this might be too restrictive for future FAQ entries which could require longer, more detailed answers. Other similar text columns in the schema are larger (e.g., inquiry.content is VARCHAR(1000), notice.content is VARCHAR(3000)). To ensure flexibility and consistency, consider increasing the size of this column, for example to VARCHAR(1000) or TEXT.

    answer     VARCHAR(1000) NOT NULL,

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🔭 Outside diff range comments (5)
src/main/java/life/mosu/mosuserver/application/examapplication/ExamApplicationService.java (1)

156-160: Avoid hard-coded lunch labels; use Lunch enum

Please replace all literal “도시락 X” and “선택 안 함” occurrences with the enum’s source of truth and add the necessary import.

ExamApplicationService.java
Replace lines 156–160:

-                examApplicationInfo.isLunchChecked() ? examApplicationInfo.lunchName() : "도시락 X",
+                examApplicationInfo.isLunchChecked() ? examApplicationInfo.lunchName() : Lunch.NONE.getLunchName(),

Add at the top of the file (with your other imports):

import life.mosu.mosuserver.domain.application.entity.Lunch;

ApplicationNotifyRequest.java
Replace around line 26:

-                examApplication.isLunchChecked() ? examApplication.lunchName() : "선택 안 함");
+                examApplication.isLunchChecked() ? examApplication.lunchName() : Lunch.NONE.getLunchName());

Also add:

import life.mosu.mosuserver.domain.application.entity.Lunch;
src/main/java/life/mosu/mosuserver/domain/application/entity/Lunch.java (1)

22-29: Prefer stable enum codes over user-facing labels

from(String lunchName) relies on the human-readable label, coupling behavior to UI text. Introduce a stable code (e.g., NONE/OPTION1/...) for parsing/storage, and map labels for display/i18n. This avoids breakage when labels change.

I can propose a minimal refactor (add code field, use @JsonCreator on code, keep lunchName for display) if desired.

src/main/java/life/mosu/mosuserver/domain/user/entity/UserJpaEntity.java (1)

109-111: Potential NPE in isMosuUser().

provider can be null. Use constant-first comparison.

-        return this.provider.equals(AuthProvider.MOSU);
+        return AuthProvider.MOSU.equals(this.provider);
src/main/resources/db/data/data.sql (1)

119-151: FAQ answer length vs schema VARCHAR(255).

faq.answer is defined as VARCHAR(255), but several answers here likely exceed 255 chars. Inserts may fail or truncate.

Either:

  • Increase column length in migration (e.g., VARCHAR(1000) or TEXT), or
  • Shorten answers.
    Prefer increasing column length to at least VARCHAR(1000) for flexibility.
src/main/java/life/mosu/mosuserver/domain/file/FileMoveFailLog.java (1)

24-25: Enum mapping missing for destinationFolder; will fail validation.

destination_folder is SMALLINT in DB. Annotate with @Enumerated to map correctly.

Option A (keep SMALLINT/ordinal):

-    private Folder destinationFolder;
+    @jakarta.persistence.Enumerated(jakarta.persistence.EnumType.ORDINAL)
+    private Folder destinationFolder;

Option B (prefer STRING for safer evolvability): change DB column to VARCHAR(50) and annotate with EnumType.STRING.

🧹 Nitpick comments (1)
src/main/resources/db/migration/V1__init.sql (1)

1-14: No foreign keys defined; risk of orphaned records.

application_id, user_id, exam_application_id, etc., are used widely without FK constraints. This compromises referential integrity.

If soft deletes and bulk loads are the concern, at least add selective FKs where safe (e.g., profile.user_id → user.user_id) and consider ON DELETE RESTRICT. Alternatively, add periodic integrity checks.

Also applies to: 350-362

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff671d9 and 7fe1691.

📒 Files selected for processing (19)
  • src/main/java/life/mosu/mosuserver/application/examapplication/ExamApplicationService.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/application/form/FormService.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserPersistenceProcessor.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/domain/application/entity/Lunch.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/domain/file/FileMoveFailLog.java (2 hunks)
  • src/main/java/life/mosu/mosuserver/domain/file/FileWithTime.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/domain/form/FormJpaEntity.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/domain/form/FormJpaRepository.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/domain/user/entity/UserJpaEntity.java (2 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/application/dto/ApplicationGuestRequest.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/auth/dto/request/SignUpAccountRequest.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/form/FormController.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/form/FormControllerDocs.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/form/dto/FormListResponse.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/form/dto/FormResponse.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/form/dto/RegisterFormRequest.java (0 hunks)
  • src/main/resources/application-base.yml (1 hunks)
  • src/main/resources/db/data/data.sql (1 hunks)
  • src/main/resources/db/migration/V1__init.sql (1 hunks)
💤 Files with no reviewable changes (11)
  • src/main/java/life/mosu/mosuserver/presentation/form/dto/FormListResponse.java
  • src/main/java/life/mosu/mosuserver/presentation/auth/dto/request/SignUpAccountRequest.java
  • src/main/java/life/mosu/mosuserver/domain/form/FormJpaRepository.java
  • src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserPersistenceProcessor.java
  • src/main/java/life/mosu/mosuserver/presentation/form/FormControllerDocs.java
  • src/main/java/life/mosu/mosuserver/presentation/application/dto/ApplicationGuestRequest.java
  • src/main/java/life/mosu/mosuserver/domain/form/FormJpaEntity.java
  • src/main/java/life/mosu/mosuserver/presentation/form/dto/RegisterFormRequest.java
  • src/main/java/life/mosu/mosuserver/presentation/form/FormController.java
  • src/main/java/life/mosu/mosuserver/application/form/FormService.java
  • src/main/java/life/mosu/mosuserver/presentation/form/dto/FormResponse.java
🔇 Additional comments (5)
src/main/resources/db/migration/V1__init.sql (1)

317-334: Unique constraints on user look good; verify existing data or migration path.

Adding uniqueness on login_id and phone_number is correct. Ensure no legacy duplicates exist to avoid migration failures.

You can run a quick check on the target DB before deploying:

SELECT login_id FROM user GROUP BY login_id HAVING COUNT(*) > 1;
SELECT phone_number FROM user GROUP BY phone_number HAVING COUNT(*) > 1;

Also applies to: 359-361

src/main/resources/application-base.yml (1)

48-48: Switching to ddl-auto=validate is correct with Flyway; be aware it will fail fast on mapping mismatches.

Given the s3key vs s3_key mismatch and enum mapping noted elsewhere, the app will not start until those are resolved.

After fixing the mappings, validate locally with: grep for Entity fields named s3Key and ensure a matching column exists in the DB.

src/main/java/life/mosu/mosuserver/domain/user/entity/UserJpaEntity.java (2)

50-51: DB-level uniqueness for phoneNumber aligns with schema. LGTM.


67-71: No action needed—builder uses named setters exclusively
I’ve confirmed that all UserJpaEntity.builder() invocations rely on chained setter methods rather than positional constructor calls, so reordering the underlying constructor parameters won’t introduce any ordering bugs. No direct uses of the all-args constructor were found.

src/main/resources/db/data/data.sql (1)

1-51: Verify schema qualifier usage in data.sql

Your seed script is hard-coding sa. as the schema qualifier in every INSERT, but your Spring config pulls the JDBC URL from ${DB_URL} without a default database name. We couldn’t find any explicit reference to a /sa database in the application YAML or environment files, so please double-check:

• Ensure your DB_URL (in .env or environment variables) points to the sa database (e.g. jdbc:mysql://host:port/sa)
• If your target database uses a different schema/name, remove the sa. prefix from all table references in src/main/resources/db/data/data.sql (lines 1–151) – also applies to the blocks at lines 53–75, 76–118, and 119–151

@RequiredArgsConstructor
public enum Lunch {
NONE("선택 안 함"),
NONE("도시락 X"),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Changing display label may impact data parsing and seeds

Updating NONE from "선택 안 함" to "도시락 X" can break Lunch.from(...) if any incoming/persisted data still uses the old label.

  • Verify Flyway migrations/seed data update old values to the new label.
  • Check API clients/admin tools are updated accordingly.

Run:

Consider documenting this change in release notes to alert downstream consumers.


🏁 Script executed:

#!/bin/bash
# Search migrations/fixtures and code for old label usage
fd -HI . | wc -l >/dev/null 2>&1  # warm up fd cache
rg -n $'선택 안 함'
rg -n $'Lunch\.from\(' -A 2
fd -HI 'V*__*.sql' src/main/resources | xargs -I{} sh -c 'echo "== {} =="; sed -n "1,200p" "{}" | rg -n $'\''선택 안 함|도시락 X'\'' || true'

Length of output: 331


🏁 Script executed:

#!/bin/bash
# Locate the Lunch enum and inspect its `from` method implementation
LUNCH_FILE=$(fd -HI 'Lunch.java' | head -n1)
echo "== $LUNCH_FILE =="
sed -n '1,200p' "$LUNCH_FILE"
echo
echo "== Checking `from` occurrences =="
rg -n 'from\(' -C 3 "$LUNCH_FILE"

Length of output: 1719


Replace legacy lunch label in code and database seeds

We’ve confirmed that Lunch.NONE is now "도시락 X", but there’s still one hard-coded reference to the old label and no in-repo SQL migrations/seed files to update. Please:

• Update src/main/java/life/mosu/mosuserver/application/notify/dto/ApplicationNotifyRequest.java (around line 26) to use "도시락 X" (or better yet, Lunch.NONE.getLunchName()) instead of "선택 안 함".
• If you maintain any external Flyway migrations or seed scripts inserting "선택 안 함", revise them to "도시락 X".
• Notify downstream API clients and admin tools of this label change (e.g., in release notes) to prevent parsing errors in Lunch.from(...).

🤖 Prompt for AI Agents
In src/main/java/life/mosu/mosuserver/domain/application/entity/Lunch.java at
line 12, the legacy lunch label "선택 안 함" has been replaced with "도시락 X" for
Lunch.NONE. To fix the issue, update
src/main/java/life/mosu/mosuserver/application/notify/dto/ApplicationNotifyRequest.java
around line 26 to use Lunch.NONE.getLunchName() instead of the hard-coded string
"선택 안 함". Also, check any external Flyway migration or seed SQL scripts for
occurrences of "선택 안 함" and replace them with "도시락 X". Finally, ensure
downstream API clients and admin tools are informed of this label change to
avoid parsing errors with Lunch.from(...).

Comment on lines +21 to 23
@Column(columnDefinition = "TEXT")
private String s3Key;

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add column name to align with migration and avoid naming mismatch.

Same s3Key vs s3key issue here.

If keeping DB column as s3key:

-    @Column(columnDefinition = "TEXT")
+    @Column(name = "s3key", columnDefinition = "TEXT")
     private String s3Key;
🤖 Prompt for AI Agents
In src/main/java/life/mosu/mosuserver/domain/file/FileMoveFailLog.java at lines
21 to 23, the field s3Key lacks an explicit column name, causing a mismatch with
the database column s3key. Fix this by adding the column name attribute to the
@Column annotation, setting it to "s3key" to align with the existing database
schema and avoid naming conflicts.

Comment on lines +20 to 21
@Column(columnDefinition = "TEXT")
private String s3Key;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add column name to align with migration and avoid naming mismatch.

To align with the schema using s3key (or choose s3_key consistently), specify the column name here.

If keeping DB column as s3key:

-    @Column(columnDefinition = "TEXT")
+    @Column(name = "s3key", columnDefinition = "TEXT")
     private String s3Key;

Alternatively, rename DB columns to s3_key and leave code as-is.

📝 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.

Suggested change
@Column(columnDefinition = "TEXT")
private String s3Key;
@Column(name = "s3key", columnDefinition = "TEXT")
private String s3Key;
🤖 Prompt for AI Agents
In src/main/java/life/mosu/mosuserver/domain/file/FileWithTime.java at lines
20-21, the field s3Key lacks an explicit column name, which may cause mismatches
with the database schema. To fix this, add the column name attribute to the
@Column annotation, specifying the exact column name used in the database (e.g.,
"s3key" or "s3_key") to ensure consistency between the entity and the migration
schema.

Comment on lines +27 to +40
CREATE TABLE banner
(
deleted BIT(1) NOT NULL,
id BIGINT AUTO_INCREMENT NOT NULL,
file_name VARCHAR(255) NULL,
s3key TEXT NULL,
visibility VARCHAR(255) NULL,
created_at datetime NULL,
updated_at datetime NULL,
title VARCHAR(255) NULL,
dead_line datetime NULL,
banner_link VARCHAR(255) NULL,
CONSTRAINT pk_banner PRIMARY KEY (id)
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Column name mismatch: s3Key vs s3key (will fail ddl-auto=validate).

Entity fields are named s3Key and, with Spring's default physical naming strategy, map to s3_key. This migration creates columns named s3key (no underscore) in multiple tables, which will cause startup validation failures.

Two viable fixes (pick one and apply consistently):

  • Prefer schema-first: Rename DB columns to s3_key everywhere and update data.sql accordingly.
  • Prefer code-first: Keep s3key in DB but annotate entity fields with @column(name = "s3key") (including FileWithTime and FileMoveFailLog).

If you choose schema-first, apply diffs like:

-    s3key       TEXT NULL,
+    s3_key      TEXT NULL,

Repeat for tables: banner, event, exam_ticket_image, inquiry_answer_attachment, inquiry_attachment, notice_attachment, file_move_fail_log.

Also applies to: 51-65, 109-117, 171-179, 181-189, 204-212, 132-141

🤖 Prompt for AI Agents
In src/main/resources/db/migration/V1__init.sql around lines 27 to 40, the
column name s3key does not match the entity field s3Key, which maps to s3_key by
default, causing ddl-auto=validate failures. To fix this, rename the s3key
column to s3_key in this table and all other affected tables (banner, event,
exam_ticket_image, inquiry_answer_attachment, inquiry_attachment,
notice_attachment, file_move_fail_log) and update data.sql accordingly if using
schema-first approach; alternatively, if preferring code-first, keep s3key as is
in the DB and add @Column(name = "s3key") annotations to the corresponding
entity fields in FileWithTime and FileMoveFailLog classes. Apply the chosen fix
consistently across all mentioned tables and lines.

Comment on lines +132 to +141
CREATE TABLE file_move_fail_log
(
id BIGINT AUTO_INCREMENT NOT NULL,
created_at datetime NULL,
updated_at datetime NULL,
faq_id BIGINT NULL,
s3key TEXT NULL,
destination_folder SMALLINT NULL,
CONSTRAINT pk_filemovefaillog PRIMARY KEY (id)
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Enum storage for FileMoveFailLog.destination_folder mismatched with code.

Schema uses SMALLINT for destination_folder (ordinal), but the entity lacks @Enumerated. With ddl-auto=validate, mapping will fail.

Either:

  • Keep SMALLINT and annotate entity with @Enumerated(EnumType.ORDINAL), or
  • Change DB column to VARCHAR and use @Enumerated(EnumType.STRING).
🤖 Prompt for AI Agents
In src/main/resources/db/migration/V1__init.sql lines 132 to 141, the
destination_folder column is defined as SMALLINT but the corresponding entity
lacks the @Enumerated annotation, causing mapping issues with ddl-auto=validate.
To fix this, either keep the SMALLINT type and add @Enumerated(EnumType.ORDINAL)
to the entity's destination_folder field, or change the destination_folder
column type in the database to VARCHAR and annotate the entity with
@Enumerated(EnumType.STRING) accordingly.

Comment on lines +244 to +255
CREATE TABLE payment_failure_log
(
payment_failure_id BIGINT AUTO_INCREMENT NOT NULL,
created_at datetime NULL,
updated_at datetime NULL,
payment_id BIGINT NOT NULL,
exam_application_id BIGINT NOT NULL,
application_id BIGINT NULL,
reason VARCHAR(255) NOT NULL,
snapshot TEXT NULL,
CONSTRAINT pk_payment_failure_log PRIMARY KEY (payment_failure_id)
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add unique constraints for payment_key and order_id to prevent duplicates.

payment.order_id is NOT NULL, and payment_key often maps 1:1 with providers. Duplicates will cause reconciliation issues.

Consider adding:

ALTER TABLE payment ADD CONSTRAINT uc_payment_order UNIQUE (order_id);
ALTER TABLE payment ADD CONSTRAINT uc_payment_key UNIQUE (payment_key);

Also applies to: 224-242

🤖 Prompt for AI Agents
In src/main/resources/db/migration/V1__init.sql around lines 224 to 242 and 244
to 255, the payment table lacks unique constraints on order_id and payment_key,
which can lead to duplicate entries and reconciliation issues. Add unique
constraints by altering the payment table to include UNIQUE constraints on
order_id and payment_key columns using ALTER TABLE statements. This will enforce
uniqueness and prevent duplicate records.

@mosu-dev mosu-dev deleted a comment from coderabbitai bot Aug 11, 2025
@wlgns12370 wlgns12370 merged commit 9aa1479 into develop Aug 11, 2025
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[🛠 기능 구현] flyway DB 마이그레이션

1 participant