Mysql을 JPA로 사용하는데 대문자로 만든 테이블이있고 name으로 테이블을 대문자로 설정해둠에도 불구하고 계속
같은 이름의 소문자 테이블을 생성해서 값을 넣음.........
결론은 yml의 JPA Naming Strategy 변경
// ========================================
// JPA/Hibernate 테이블명 변환 규칙
// ========================================
/*
1. 기본 규칙 (Hibernate 5.0+):
- Entity 클래스명을 테이블명으로 사용
- CamelCase → snake_case 변환
- 대문자 → 소문자 변환
*/
// 예시 1: 자동 변환
@Entity
public class UserAccount { // 클래스명
}
// → 테이블명: user_account (소문자 + 언더스코어)
@Entity
public class RefreshToken {
}
// → 테이블명: refresh_token
// ========================================
// Naming Strategy별 동작 방식
// ========================================
// 1. SpringPhysicalNamingStrategy (Spring Boot 기본)
// application.yml에서 설정 안 하면 기본적으로 사용됨
/*
동작:
- CamelCase → snake_case
- 대문자 → 소문자
- UserAccount → user_account
- RefreshToken → refresh_token
*/
// 2. PhysicalNamingStrategyStandardImpl (Hibernate 기본)
/*
동작:
- 변환하지 않음
- Entity명 그대로 사용
- UserAccount → UserAccount (그대로)
- 단, @Table 어노테이션이 있으면 그것 우선
*/
// 3. ImplicitNamingStrategyLegacyJpaImpl
/*
동작:
- JPA 1.0 방식
- 클래스명 그대로 사용
*/
// ========================================
// Spring Boot에서의 기본 동작
// ========================================
// application.yml에 아무 설정 없으면:
spring:
jpa:
hibernate:
naming:
physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
/*
결과:
@Entity
public class User {
}
→ 테이블명: user (소문자)
@Entity
public class UserAccount {
}
→ 테이블명: user_account (소문자 + 언더스코어)
*/
// ========================================
// @Table 어노테이션 우선순위
// ========================================
@Entity
@Table(name = "USER_ACCOUNT") // 명시적 지정
public class User {
}
// → 테이블명: USER_ACCOUNT (지정한 대로)
@Entity
@Table(name = "`USER_ACCOUNT`") // 백틱으로 강제
public class User {
}
// → 테이블명: USER_ACCOUNT (대소문자 강제)
// ========================================
// MySQL 대소문자 처리 특성
// ========================================
/*
MySQL 대소문자 규칙:
1. Windows: 대소문자 구분 안함 (case-insensitive)
2. Linux/Unix: 대소문자 구분함 (case-sensitive)
3. lower_case_table_names 설정에 따라 달라짐
MySQL 설정 확인:
SHOW VARIABLES LIKE 'lower_case_table_names';
값별 의미:
- 0: 대소문자 구분 (Linux 기본)
- 1: 소문자로 저장하고 비교 시 대소문자 무시 (Windows 기본)
- 2: 대소문자 그대로 저장하지만 비교 시 소문자로 변환
*/
// ========================================
// 현재 문제 상황 분석
// ========================================
/*
문제 상황:
1. Entity: @Table(name = "USER_ACCOUNT")
2. 실제 DB: USER_ACCOUNT 테이블 존재
3. JPA 쿼리: SELECT ... FROM user_account (소문자로 생성됨)
4. 오류: Table 'cms.user_account' doesn't exist
원인:
- Spring Boot의 기본 Naming Strategy가 소문자 변환
- @Table 어노테이션이 있어도 추가 변환 발생
- MySQL에서 user_account 테이블을 찾을 수 없음
*/
// ========================================
// 해결 방법들
// ========================================
// 방법 1: Naming Strategy 변경 (권장)
// application.yml
spring:
jpa:
hibernate:
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
/*
효과:
- @Table에 지정한 이름 그대로 사용
- USER_ACCOUNT → USER_ACCOUNT (변환 안함)
*/
// 방법 2: 백틱 사용
@Entity
@Table(name = "`USER_ACCOUNT`")
public class User {
@Id
@Column(name = "`USER_ID`")
private String userId;
}
// 방법 3: globally_quoted_identifiers 설정
spring:
jpa:
properties:
hibernate:
globally_quoted_identifiers: true
// 방법 4: 소문자 테이블 생성 (가장 확실)
// JPA가 원하는 소문자 테이블을 만들어주기
// ========================================
// 권장 해결책
// ========================================
// 1. application.yml 수정 (가장 깔끔)
spring:
jpa:
hibernate:
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
// 2. Entity는 그대로
@Entity
@Table(name = "USER_ACCOUNT") // 백틱 없이
public class User {
@Column(name = "USER_ID")
private String userId;
}
/*
결과:
- @Table에 지정한 "USER_ACCOUNT" 그대로 사용
- 더 이상 소문자 변환 안함
- 기존 대문자 테이블과 정확히 매칭
*/
// ========================================
// 테스트 방법
// ========================================
/*
1. application.yml에 Naming Strategy 추가
2. 서버 재시작
3. show-sql: true로 실제 SQL 확인
4. 로그에서 "SELECT ... FROM USER_ACCOUNT" 나오는지 확인
*/
🎯 JPA 테이블명 변환 규칙
❓ 질문: JPA는 원래 소문자로 찾나요?
답: 아닙니다! JPA 자체는 소문자로 변환하지 않습니다. Spring Boot가 기본적으로 소문자 변환을 합니다.
🔍 변환 과정
Spring Boot 기본 동작
java
@Entity
public class UserAccount { // 클래스명
}
// → user_account (소문자 + 언더스코어)
@Entity
@Table(name = "USER_ACCOUNT") // 명시적 지정
public class User {
}
// → user_account (여전히 소문자로 변환됨!)
순수 Hibernate 동작
java
@Entity
@Table(name = "USER_ACCOUNT")
public class User {
}
// → USER_ACCOUNT (지정한 그대로 사용)
🔧 현재 문제 원인
- Spring Boot 기본 설정: 모든 테이블명을 소문자로 변환
- 실제 테이블: USER_ACCOUNT (대문자)
- JPA 쿼리: SELECT ... FROM user_account (소문자)
- 결과: 테이블을 찾을 수 없음
⚡ 가장 깔끔한 해결책
application.yml에 이 설정 추가:
yaml
spring:
jpa:
hibernate:
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
효과:
- @Table에 지정한 이름 그대로 사용
- 더 이상 소문자 변환 안함
- USER_ACCOUNT → USER_ACCOUNT (그대로)
🎯 정리
- JPA 자체: 변환 안함
- Spring Boot: 기본적으로 소문자 변환
- 해결책: Naming Strategy 변경이 가장 깔끔
결론: Spring Boot가 친절하게(?) 소문자로 바꿔주고 있었습니다! 🚀