JPA 테이블 소문자로 인식하는 오류

2025. 6. 14. 13:44·Web

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 (지정한 그대로 사용)

🔧 현재 문제 원인

  1. Spring Boot 기본 설정: 모든 테이블명을 소문자로 변환
  2. 실제 테이블: USER_ACCOUNT (대문자)
  3. JPA 쿼리: SELECT ... FROM user_account (소문자)
  4. 결과: 테이블을 찾을 수 없음

⚡ 가장 깔끔한 해결책

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가 친절하게(?) 소문자로 바꿔주고 있었습니다! 🚀

저작자표시 비영리 변경금지 (새창열림)
'Web' 카테고리의 다른 글
  • 토큰 어디에 저장하지
  • 소셜로그인 트러블슈팅
  • 빌드 에러
  • 기술스택
9na0
9na0
응애
  • 9na0
    구나딩
    9na0
  • 전체
    오늘
    어제
    • 분류 전체보기 (211)
      • Web (118)
      • Java (28)
      • 데이터베이스 (14)
      • 세팅 (12)
      • 과제 (3)
      • 쪽지시험 (2)
      • 정보처리기사 (4)
      • 서버 (25)
  • 블로그 메뉴

    • 링크

      • 포폴
      • 구깃
    • 공지사항

    • 인기 글

    • 태그

      net4
      macbook pro m4
      file25
      net5~10
      Oracle
      file25_t
      java_io1~10
      net1
      datalist
      re_java10
      noticewriteok
      io_dto
      net3
      spring-boot
      ab1
      exam1_1~10
      notice_writer
      file24
      re2
      net2
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    9na0
    JPA 테이블 소문자로 인식하는 오류
    상단으로

    티스토리툴바