1. 문제상황
Spring 백단에서 프로퍼티별 개발환경을 나누고 로컬에선 H2db, 개발서버에선 aws rds mysql 8.0 을 사용하도록 datasource를 연결하였다.
그리고 h2db쪽에서는 쿼리가 잘 날라가는 걸 확인.
테스트 완료후 ec2에 배포하고 개발서버에서 실행했는데 table이 없다고 나옴.
2. 시도한 방법들
- JPA Naming Strategy
기본적으로 아무런 설정을 하지 않으면 @Table 의 지정한 name 이 대 소문자를 구분하여 쿼리가 날라간다. 즉 , mysql 에서는 테이블 명이 USERS 였고 JPA entity 의 name 은 users 였기 때문에 테이블을 찾지 못하는것.
그래서 별도의 namingStrategy를 프로퍼티에서 지정해주거나 엔티티에서 Table name을 지정할 때 대문자로하면 된다..
그러나 DB tool 내에서의 쿼리콘솔에서도 대소문자 구분하고 싶지 않은데 ... 일단 근본적인 해결방법은 아닌 것 같다.
- lower_case_table_names
mysql 에서 테이블이름에 대해 대 소문자를 구분하는지에 대한 설정을 할 수 있다.
mysql 이 설치된 경로로 들어가 my.cnf 에서 lower_case_table_names = 1 로 설정하면 되지만 AWS RDS에서는 할 수 없기 때문에 RDS 파라미터 설정에서 바꿔줘야한다.
0 -> 1 로 변경.
뭣 ..
파라미터 그룹이 연결되어있어서 변경이 안된다니깐 default 로 다시 바꾸고 파라미터 수정 재시도.
뭣..
찾아보니 mysql 8.0 부터는 DB를 최초 생성했을 때만 설정할 수 있다고 나온다..
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/MySQL.KnownIssuesAndLimitations.html#MySQL.Concepts.ParameterNotes
3. 결론
결론적으로 내가 손 댈수 있는건 네이밍 전략밖에 없었다.
application.yml 의 physical-strategy를 CustomNamingStrategy 를 PhysicalNamingStrategy 인터페이스를 구현받아 사용하여 해결하였다.
package com.greenroom.server.api.utils;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
public class JpaCustomPhysicalNamingStrategy implements PhysicalNamingStrategy {
@Override
public Identifier toPhysicalCatalogName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
if(identifier == null){
return null;
}
return convertToSnakeCase(identifier);
}
@Override
public Identifier toPhysicalColumnName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
if(identifier == null){
return null;
}
return convertToSnakeCase(identifier);
}
@Override
public Identifier toPhysicalSchemaName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
if(identifier == null){
return null;
}
return convertToSnakeCase(identifier);
}
@Override
public Identifier toPhysicalSequenceName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
if(identifier == null){
return null;
}
return convertToSnakeCase(identifier);
}
@Override
public Identifier toPhysicalTableName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
if(identifier == null){
return null;
}
return convertToSnakeCaseAndUpperCase(identifier);
}
private Identifier convertToSnakeCase(final Identifier identifier) {
final String regex = "([a-z])([A-Z])";
final String replacement = "$1_$2";
final String newName = identifier.getText()
.replaceAll(regex, replacement)
.toLowerCase();
return Identifier.toIdentifier(newName);
}
private Identifier convertToSnakeCaseAndUpperCase(final Identifier identifier) {
final String regex = "([a-z])([A-Z])";
final String replacement = "$1_$2";
final String newName = identifier.getText()
.replaceAll(regex, replacement)
.toUpperCase();
return Identifier.toIdentifier(newName);
}
}
적용해보면 from 절의 테이블 지정이 대문자로 바뀌어있는 것을 볼 수 있다.