Skip to content

Commit b99cec9

Browse files
authored
Merge pull request #297 from asowjdan/fix/member
Fix[member]:로컬과 소셜 회원의 기본 키 값 중복 제거
2 parents 4dc4e05 + 179b36f commit b99cec9

File tree

6 files changed

+176
-3
lines changed

6 files changed

+176
-3
lines changed

backend/sql/member_id_sequence.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
-- ============================================
2+
-- 공유 member_id 시퀀스 테이블 생성
3+
-- ============================================
4+
-- 주의: 기존 배포 환경에 데이터가 있다면
5+
-- backend/sql/migrate_member_id_sequence.sql을 먼저 실행해야 합니다!
6+
-- ============================================
7+
8+
CREATE TABLE IF NOT EXISTS member_id_sequence (
9+
sequence_name VARCHAR(255) NOT NULL PRIMARY KEY,
10+
next_val BIGINT NOT NULL
11+
);
12+
13+
-- 초기값 설정: 신규 설치 시 1부터 시작
14+
-- 기존 환경은 마이그레이션 스크립트로 처리
15+
INSERT INTO member_id_sequence (sequence_name, next_val)
16+
VALUES ('member_id_seq', 1)
17+
ON DUPLICATE KEY UPDATE sequence_name = sequence_name;
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
-- ============================================
2+
-- member_id 중복 해결 및 공유 시퀀스 설정 마이그레이션
3+
-- ============================================
4+
-- 실행 전 주의사항:
5+
-- 1. 반드시 데이터베이스 백업을 먼저 수행하세요!
6+
-- 2. 서비스를 중단한 상태에서 실행하세요 (데이터 정합성)
7+
-- 3. 실행 후 애플리케이션을 재시작하세요
8+
-- ============================================
9+
10+
-- 1단계: 현재 상태 확인
11+
SELECT '=== 현재 member 테이블 ===' as info;
12+
SELECT COUNT(*) as count, MIN(member_id) as min_id, MAX(member_id) as max_id FROM member;
13+
14+
SELECT '=== 현재 oauth2_member 테이블 ===' as info;
15+
SELECT COUNT(*) as count, MIN(member_id) as min_id, MAX(member_id) as max_id FROM oauth2_member;
16+
17+
SELECT '=== 중복 확인 ===' as info;
18+
SELECT m.member_id, 'BOTH' as status
19+
FROM member m
20+
INNER JOIN oauth2_member o ON m.member_id = o.member_id;
21+
22+
-- 2단계: oauth2_member의 member_id를 재할당
23+
-- member 테이블의 최대값 이후부터 시작
24+
SET @max_member_id := (SELECT COALESCE(MAX(member_id), 0) FROM member);
25+
26+
SELECT CONCAT('member 테이블 최대 ID: ', @max_member_id) as info;
27+
28+
-- 임시 테이블로 매핑 생성
29+
CREATE TEMPORARY TABLE IF NOT EXISTS oauth2_member_id_mapping (
30+
old_member_id BIGINT,
31+
new_member_id BIGINT,
32+
PRIMARY KEY (old_member_id)
33+
);
34+
35+
-- 매핑 데이터 생성
36+
INSERT INTO oauth2_member_id_mapping (old_member_id, new_member_id)
37+
SELECT
38+
member_id as old_member_id,
39+
@max_member_id + ROW_NUMBER() OVER (ORDER BY member_id) as new_member_id
40+
FROM oauth2_member
41+
ORDER BY member_id;
42+
43+
SELECT '=== 매핑 테이블 ===' as info;
44+
SELECT * FROM oauth2_member_id_mapping;
45+
46+
-- 3단계: 외래키 제약 확인 (있다면 비활성화)
47+
SET FOREIGN_KEY_CHECKS = 0;
48+
49+
-- 4단계: 연관 테이블 업데이트 (member_id를 외래키로 가진 테이블만)
50+
-- Post 테이블 (FK: member_id)
51+
UPDATE post p
52+
INNER JOIN oauth2_member_id_mapping m ON p.member_id = m.old_member_id
53+
SET p.member_id = m.new_member_id;
54+
55+
-- PollVote 테이블 (FK: member_id)
56+
UPDATE poll_vote pv
57+
INNER JOIN oauth2_member_id_mapping m ON pv.member_id = m.old_member_id
58+
SET pv.member_id = m.new_member_id;
59+
60+
-- History 테이블 (FK: member_id)
61+
UPDATE history h
62+
INNER JOIN oauth2_member_id_mapping m ON h.member_id = m.old_member_id
63+
SET h.member_id = m.new_member_id;
64+
65+
-- 5단계: oauth2_member 테이블 업데이트
66+
UPDATE oauth2_member o
67+
INNER JOIN oauth2_member_id_mapping m ON o.member_id = m.old_member_id
68+
SET o.member_id = m.new_member_id;
69+
70+
-- 6단계: 외래키 제약 다시 활성화
71+
SET FOREIGN_KEY_CHECKS = 1;
72+
73+
-- 7단계: 시퀀스 테이블 생성
74+
CREATE TABLE IF NOT EXISTS member_id_sequence (
75+
sequence_name VARCHAR(255) NOT NULL PRIMARY KEY,
76+
next_val BIGINT NOT NULL
77+
);
78+
79+
-- 8단계: 초기값 설정 (재할당 후 최대값 + 1)
80+
INSERT INTO member_id_sequence (sequence_name, next_val)
81+
SELECT 'member_id_seq', COALESCE(MAX(max_id), 0) + 1
82+
FROM (
83+
SELECT COALESCE(MAX(member_id), 0) as max_id FROM member
84+
UNION ALL
85+
SELECT COALESCE(MAX(member_id), 0) as max_id FROM oauth2_member
86+
) as max_values
87+
ON DUPLICATE KEY UPDATE next_val = VALUES(next_val);
88+
89+
-- 9단계: 최종 상태 확인
90+
SELECT '=== 마이그레이션 후 member 테이블 ===' as info;
91+
SELECT COUNT(*) as count, MIN(member_id) as min_id, MAX(member_id) as max_id FROM member;
92+
93+
SELECT '=== 마이그레이션 후 oauth2_member 테이블 ===' as info;
94+
SELECT COUNT(*) as count, MIN(member_id) as min_id, MAX(member_id) as max_id FROM oauth2_member;
95+
96+
SELECT '=== 중복 확인 (0건이어야 함) ===' as info;
97+
SELECT m.member_id, 'BOTH' as status
98+
FROM member m
99+
INNER JOIN oauth2_member o ON m.member_id = o.member_id;
100+
101+
SELECT '=== 시퀀스 초기값 ===' as info;
102+
SELECT * FROM member_id_sequence;
103+
104+
-- 임시 테이블 삭제
105+
DROP TEMPORARY TABLE IF EXISTS oauth2_member_id_mapping;
106+
107+
SELECT '=== 마이그레이션 완료! ===' as info;

backend/src/main/java/com/ai/lawyer/domain/member/entity/Member.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,15 @@
2323
public class Member implements MemberAdapter {
2424

2525
@Id
26-
@GeneratedValue(strategy = GenerationType.IDENTITY)
26+
@GeneratedValue(strategy = GenerationType.TABLE, generator = "member_id_gen")
27+
@TableGenerator(
28+
name = "member_id_gen",
29+
table = "member_id_sequence",
30+
pkColumnName = "sequence_name",
31+
valueColumnName = "next_val",
32+
pkColumnValue = "member_id_seq",
33+
allocationSize = 1
34+
)
2735
@Column(name = "member_id", nullable = false)
2836
private Long memberId;
2937

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.ai.lawyer.domain.member.entity;
2+
3+
import jakarta.persistence.*;
4+
import lombok.*;
5+
6+
/**
7+
* Member와 OAuth2Member가 공유하는 member_id 시퀀스 테이블
8+
* JPA의 @TableGenerator가 자동으로 관리하는 테이블을 엔티티로 명시
9+
*/
10+
@Entity
11+
@Table(name = "member_id_sequence")
12+
@Getter
13+
@Setter
14+
@NoArgsConstructor
15+
@AllArgsConstructor
16+
@Builder
17+
@ToString
18+
public class MemberIdSequence {
19+
20+
/**
21+
* 시퀀스 이름 (Primary Key)
22+
* Member와 OAuth2Member는 'member_id_seq' 값을 공유
23+
*/
24+
@Id
25+
@Column(name = "sequence_name", nullable = false)
26+
private String sequenceName;
27+
28+
/**
29+
* 다음에 할당될 member_id 값
30+
* JPA의 @TableGenerator가 자동으로 증가시킴
31+
*/
32+
@Column(name = "next_val", nullable = false)
33+
private Long nextVal;
34+
}

backend/src/main/java/com/ai/lawyer/domain/member/entity/OAuth2Member.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,15 @@
2424
public class OAuth2Member implements MemberAdapter {
2525

2626
@Id
27-
@GeneratedValue(strategy = GenerationType.IDENTITY)
27+
@GeneratedValue(strategy = GenerationType.TABLE, generator = "member_id_gen")
28+
@TableGenerator(
29+
name = "member_id_gen",
30+
table = "member_id_sequence",
31+
pkColumnName = "sequence_name",
32+
valueColumnName = "next_val",
33+
pkColumnValue = "member_id_seq",
34+
allocationSize = 1
35+
)
2836
@Column(name = "member_id", nullable = false)
2937
private Long memberId;
3038

backend/src/main/resources/data.sql

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)