legacy/JPA

[JPA-Error] Table [DB명.Table명] doesn't exist 해결방법

heemang_e 2024. 2. 21. 15:10

문제 발생

스프링부트에서 테이블을 생성하여 값을 저장하려고 하면 다음과 같은 오류가 발생했다.

org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute statement [Table 'cicd_db.users' doesn't exist] [insert into users (age,username) values (?,?)]; SQL [insert into users (age,username) values (?,?)]

문제 원인

"Table 'cicd_db.users' doesn't exist" 이부분이 핵심인 듯하다. 나는 "Users" 테이블에 데이터를 삽입하려고 하는데 실제로는 "cicd_db.users" 테이블에 삽입하려고 시도하고 있다.

나는 DB명으로 cicd_db를 사용했고, 데이터를 삽입하려고 하는 테이블명은 "users"였다. 보아하니 테이블명으로 insert 하는 것이 아닌 DB명.테이블명으로 insert 하려고 시도한다.

User.class

@Getter
@Entity
@Table(name = "USERS")
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id")
    private Long id;

    private String username;
    private int age;
}

application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: ${SPRING_DATASOURCE_URL}
    username: ${SPRING_DATASOURCE_USERNAME}
    password: ${SPRING_DATASOURCE_PASSWORD}

  # JPA 설정
  jpa:
    database: mysql
    database-platform: org.hibernate.dialect.MySQLDialect
    hibernate:
      ddl-auto: none
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQLDialect
        format_sql: true      # 쿼리 로그 포맷 (정렬)
        show_sql: true        # 쿼리 로그 출력

Test.class

@SpringBootTest
@Transactional
class UserServiceTest {

    @Autowired
    UserService userService;

    @Test
    @DisplayName("사용자 등록")
    void saveUser() {
        User user = User.builder()
            .username("이희망")
            .age(99)
            .build();
        User savedUser = userService.save(user);

        assertThat(savedUser).isEqualTo(user);
        assertThat(savedUser.getUsername()).isEqualTo("이희망");
        assertThat(savedUser.getAge()).isEqualTo(99);
    }
}

 

application.yml 파일을 보면 "ddl-auto: none"을 사용하고 있다. hibernate는 "ddl-auto: none"을 사용하면 어떤 DDL 작업도 수행하지 않는다. 따라서 Entity 클래스에 정의된 테이블이나 스키마가 실제 데이터베이스에 존재해야 한다. 즉, 테이블이나 스키마를 자동으로 생성하거나 업데이트하지 않는다. 따라서 문제가 발생한 것이다.

문제 해결

"ddl-auto: none" -> "ddl-auto: create"로 변경한다. "ddl-auto: create"의 경우 hibernate가 Entity 클래스를 기반으로 데이터베이스 스키마를 생성하게 되어 문제가 해결된다. 

여기서 주의할 점은 실제 운영환경에서는 "ddl-auto: create"를 사용해서는 안 된다. 왜냐하면 운영 환경에서는 스키마를 자동으로 생성하거나 변경해서는 안 되기 때문이다. 실제 운영환경에서는 "ddl-auto: validate" 또는 비워두는 것이 좋다.