그 외 공부/트러블 슈팅
MySQL 예약어 사용으로 인한 JPA 데이터베이스 자동 생성 실패 문제
SeongOnion
2022. 7. 28. 20:37
728x90
문제 상황
스프링 + JPA에 MySQL을 연결해 사용하는 상황에서 “Group”이라는 엔티티를 정의한 후, yml 파일의 jpa.hibernate.ddl-auto 설정을 create로 하여 엔티티 정보에 따라 테이블을 jpa가 자동으로 생성하도록 처리해주었다.
spring:
jpa:
hibernate:
ddl-auto: create # 테이블 자동 생성
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
database: mysql
하지만 서버를 켰을 때, SQL syntax error로 인해 “group” 테이블을 생성하는데 실패했다는 메시지를 뿜으며 테이블이 제대로 생성되지 않았다.
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "create table group (id bigint not null auto_increment, explanation varchar(255), name varchar(255), primary key (id)) engine=InnoDB" via JDBC Statement
Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group (id bigint not null auto_increment, explanation varchar(255), name varchar' at line 1
원인 파악
테이블 작성에 대한 쿼리를 내가 직접 짠게 아닌데 syntax error가 떠서 대체 뭘 어떻게 해야하나 싶었다.
실제로 연결된 MySQL을 살펴보니, 다른 테이블들은 정상적으로 생성이 됐는데 group 테이블만 생성이 되지 않은 상태였다.
얼마간의 삽질 후에 알아낸 원인은 ‘group’이 MySQL에서 사용하는 예약어였기 때문이다..
MySQL :: MySQL 8.0 Reference Manual :: 9.3 Keywords and Reserved Words
CREATE TABLE group
테이블 생성 쿼리에서 group을 테이블명으로 인식하지 못하고 예약어로 사용하게 됐고, 따라서 Syntax error가 발생한 것이다.
해결방안
엔티티 객체에 테이블명을 따옴표로 감싸 재정의해줌으로써 문제를 해결할 수 있었다.
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
@Table(name = "\"group\"") // 테이블명 따옴표로 처리
public class Group {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String explanation;
}
그 밖에 repository에서 @Query
를 사용해 JPQL을 정의해준 경우에도, 테이블에 대한 alias를 예약어로 사용하면 Syntax error가 발생할 수 있다.
// 예약어 관련 Syntax error 발생
@Repository
public interface GroupRepository extends JpaRepository<Group, Long> {
@Query("SELECT group from Group AS group where group.name = :name")
Optional<Group> findByName(@Param("name") String name);
}
// 정상적으로 작동
@Repository
public interface GroupRepository extends JpaRepository<Group, Long> {
@Query("SELECT g from Group AS g where g.name = :name")
Optional<Group> findByName(@Param("name") String name);
}