Caused by: org.hibernate.exception.SQLGrammarException: JDBC exception executing SQL
네이티브 SQL을 사용 도중 다음과 같은 오류가 발생하였다. 오류 내용을 보면, 네이티브 SQL을 분석했지만, DB에 productprice라는 컬럼이 없다는 오류였다.
Caused by: org.hibernate.exception.SQLGrammarException: JDBC exception executing SQL [SELECT * FROM product p WHERE p.productprice > 2000] [(conn=1050) Unknown column 'p.productprice' in 'where clause'] [n/a]
아래는 ProductEntity와 ProductRepository에 작성한 네이티브 쿼리이다.
@Entity
@Table(name = "product")
public class ProductEntity extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long productId;
@Column(length = 500, nullable = false)
String productName;
@Min(500)
@Max(10000)
Integer productPrice;
Integer productStock;
}
public interface ProductRepository extends JpaRepository<Product, Long> {
@Query(value = "SELECT * FROM productEntity p WHERE p.productprice > 2000", nativeQuery = true)
List<Product> findByPriceBasisNativeQuery();
}
그러나 JPA를 통해 생성된 테이블을 보면, 컬럼명이 다름을 알 수 있다.
즉, 네이티브 SQL에서 productprice라고 작성하였지만 실제 DB에는 product_price로 되어 있기 때문에 컬럼을 찾지 못한다는 것이다.
JPQL은 JPA 엔티티를 기반으로 작동하는 반면, 네이티브 SQL은 데이터베이스의 실제 테이블과 컬럼을 직접 사용하기 때문에 컬럼명을 맞춰주어야 한다.
다음과 같이 p.productprice를 p.product_price로 변경하여 에러를 해결하였다.
@Query(value = "SELECT * FROM product p WHERE p.product_price > 2000", nativeQuery = true)
List<Product> findByPriceBasisNativeQuery();
Entity와 DB 컬럼명이 다른 이유
Entity와 DB의 컬럼명이 다른 이유는 데이터베이스에서 일반적으로 snake case(언더스코어 사용)를 많이 사용하는 반면, 코드에서는 가독성을 높이기 위해 camel case(카멜 표기법)을 주로 사용하기 때문이다.
Spring JPA는 기본적으로 PhysicalNamingStrategyStandardImpl을 사용하며, 이 전략은 camel case를 snake case로 자동 변환한다. 따라서 productPrice라는 컬럼명을 지정하더라도, 실제 DB에는product_price로 저장된다.
snake case로 자동 변환되는 것이 불편하다면, application.properties에 다음과 같이 작성하여 자동 변환을 피할 수 있다.
# 언더바 자동변경 방지
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
결과적으로, JPQL에서 사용하는 컬럼 이름은 데이터베이스의 실제 컬럼 이름과 일치해야 오류를 피할 수 있다.
참고
spring.jpa.hibernate.naming.physical-strategy 전략 변경 (tistory.com)