Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -2,11 +2,14 @@

import com.example.solidconnection.common.BaseEntity;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import java.util.ArrayList;
import java.util.List;
import lombok.AccessLevel;
Expand All @@ -17,6 +20,12 @@
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(uniqueConstraints = {
@UniqueConstraint(
name = "uk_chat_room_mentoring_id",
columnNames = {"mentoring_id"}
Comment thread
Gyuhyeok99 marked this conversation as resolved.
Outdated
)
})
public class ChatRoom extends BaseEntity {

@Id
Expand All @@ -25,6 +34,9 @@ public class ChatRoom extends BaseEntity {

private boolean isGroup = false;

@Column(name = "mentoring_id")
private Long mentoringId;

@OneToMany(mappedBy = "chatRoom", cascade = CascadeType.ALL)
@BatchSize(size = 10)
private final List<ChatParticipant> chatParticipants = new ArrayList<>();
Expand All @@ -35,4 +47,9 @@ public class ChatRoom extends BaseEntity {
public ChatRoom(boolean isGroup) {
this.isGroup = isGroup;
}

public ChatRoom(Long mentoringId, boolean isGroup) {
this.mentoringId = mentoringId;
this.isGroup = isGroup;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ALTER TABLE chat_room
ADD COLUMN mentoring_id BIGINT;
Comment thread
Gyuhyeok99 marked this conversation as resolved.
Outdated

ALTER TABLE chat_room
ADD CONSTRAINT uk_chat_room_mentoring_id
UNIQUE (mentoring_id);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

유니크 제약의 NULL 처리와 운영 중 락 영향 점검 요청

아래 항목을 순서대로 확인해 주세요.
1) NULL-UNIQUE 동작 차이 검증. 대부분의 PostgreSQL/MySQL은 UNIQUE 컬럼에 대해 다중 NULL을 허용하지만, SQL Server는 기본적으로 NULL을 1개만 허용합니다. mentoring_id를 nullable로 유지하며 “값이 있을 때만 유일”을 원하신다면, DB 벤더가 SQL Server가 아닌지 반드시 확인해 주세요. 대안으로 벤더가 SQL Server/PostgreSQL인 경우 “mentoring_id IS NOT NULL” 조건의 필터드(부분) 유니크 인덱스가 더 안전합니다.
2) 운영 락 영향 최소화. ALTER TABLE … ADD CONSTRAINT는 대체로 테이블-레벨 락을 유발합니다. 대용량 테이블/피크 타임 배포라면 Postgres 기준 CREATE UNIQUE INDEX CONCURRENTLY(비트랜잭션) → 제약 전환(또는 인덱스만 사용) 전략을 고려해 주세요. Flyway에서 해당 마이그레이션을 트랜잭션 밖에서 실행해야 합니다.
3) 성능 관점 확인. UNIQUE 제약은 인덱스를 자동 생성하므로, mentoring_id 기반 조회 성능은 확보됩니다. 부분 유니크 인덱스를 쓰면 NULL 행이 많은 경우 인덱스 크기를 더 줄일 수 있습니다.
4) 데이터 무결성 검토. 향후 멘토링 엔티티와의 FK를 고려 중이라면(현재는 의도적으로 느슨한 결합이라면 생략 OK), 생성 시점 데이터 무결성 시나리오를 한 번 점검해 주세요.
5) 기존 데이터 영향. 기존 행에는 mentoring_id가 모두 NULL일 가능성이 크므로 현재 스크립트는 충돌 없이 적용될 확률이 높습니다. 운영 스키마에서 예외 케이스(이미 값이 있는 행)가 없는지 한번 더 확인해 주세요.

참고용(선택지, Postgres 기준):

  • 부분 유니크 인덱스
    CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS uk_chat_room_mentoring_id_notnull
    ON chat_room (mentoring_id)
    WHERE mentoring_id IS NOT NULL;

다음 스크립트로 DB 벤더 및 설정 단서를 빠르게 확인할 수 있어요. 결과 공유 부탁드려요.


🏁 Script executed:

#!/bin/bash
# DB 벤더 및 설정 단서 찾기
rg -n --no-heading -S "spring\.datasource\.url|spring\.r2dbc\.url|jdbc:|testcontainers|postgres|mysql|mariadb|sqlserver|h2" \
  src/main/resources src/test/resources || true

# Testcontainers 사용 흔적
rg -n --no-heading -S "PostgreSQLContainer|MySQLContainer|MSSQLServerContainer|MariaDBContainer|jdbc:" \
  src/test || true

Length of output: 1053


유니크 제약 및 운영 영향 체크 부탁드려요

  1. NULL–UNIQUE 동작 확인
      MySQL(InnoDB)은 UNIQUE 컬럼에 여러 개의 NULL을 허용하므로, 현재 스크립트로도 “값이 있을 때만 유일” 요구사항은 충족됩니다.

  2. 운영 중 테이블 락 최소화
      MySQL의 ALTER TABLE … ADD CONSTRAINT는 전체 테이블 락을 유발합니다. 대용량 테이블 또는 피크 타임 배포라면
      - ALTER TABLE … ALGORITHM=INPLACE 옵션 사용
      - pt-online-schema-change 등의 온라인 DDL 도구 적용
      전략을 고려해 주세요.

  3. 인덱스 및 성능 검토
      MySQL은 UNIQUE 제약 추가 시 자동으로 인덱스를 생성합니다. 조회 성능은 확보되지만, MySQL은 부분 유니크 인덱스를 지원하지 않아
      널이 많은 경우 인덱스 크기 최적화 옵션은 제한적입니다.

  4. 데이터 무결성 시나리오 점검
      향후 mentoring 엔티티와 FK 연계를 계획 중이라면, 제약 생성 시점의 데이터 무결성(기존 값·동시성) 시나리오를 한 번 검토해 주세요.

  5. 기존 데이터 영향 확인
      대부분 기존 행의 mentoring_id는 NULL 예상되므로 충돌 없이 적용 가능하지만, 혹시 NULL이 아닌 값이 있는 예외 케이스가 있는지 한번 더 살펴봐 주세요.

🤖 Prompt for AI Agents
In src/main/resources/db/migration/V28__add_mentoring_id_to_chat_room.sql lines
1 to 6, the unique constraint on mentoring_id allows multiple NULLs in MySQL,
which fits the requirement. To minimize table locking during deployment on large
or busy tables, modify the ALTER TABLE statements to use ALGORITHM=INPLACE or
apply an online schema change tool like pt-online-schema-change. Also, review
existing data for any non-NULL mentoring_id values to avoid conflicts and
consider future foreign key constraints and data integrity scenarios before
applying the migration.