오늘 JPA를 처음으로 적용시켜봤다 구글링해서 나온 예시를 하나 잡아서 DB에 적용이 되나 테스트부터 해봤다.
1.첫 번째는 Table 생성 오류였다. (파악하는데 오래 걸림)
could not prepare statement [Table "TESTY" not found (this database is empty); SQL statement:
=>분명 TESTY Table 이 생성이 되야 하는데 전혀 생성이 되지 않고 있었다..
여러가지 구글링을 해봤으나 h2 호환성 문제일수도 있다는 글들을 보고 머리아파지기 시작했지만 일단 호환성 문제는 배제하고 ChatGPT, 구글링, OverStackFlow 등 곳곳에서 검색해 문제를 알아보았다 그결과
spring:
datasource:
url: jdbc:postgresql://localhost:5432/postgres
username: postgres
password: 951951
driver-class-name: org.postgresql.Driver
h2:
console:
enabled: true # H2 DB 웹콘솔 사용하도록 설정 (http://localhost:8080/h2-console)
jpa:
database: postgresql
database-platform: org.hibernate.dialect.PostgreSQLDialect
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
format_sql: true
show_sql: true
hibernate:
ddl-auto: none
open-in-view: false
======================================================================================
수정후
======================================================================================
spring:
datasource:
url: jdbc:postgresql://localhost:5432/postgres
username: postgres
password: 951951
driver-class-name: org.postgresql.Driver
h2:
console:
enabled: true # H2 DB 웹콘솔 사용하도록 설정 (http://localhost:8080/h2-console)
jpa:
database: postgresql
database-platform: org.hibernate.dialect.PostgreSQLDialect
properties:
hibernate:
ddl-auto: create-drop
dialect: org.hibernate.dialect.PostgreSQLDialect
format_sql: true
show_sql: true
defer-datasource-initialization: true
open-in-view: false
여기서 맨 아랫줄에서 두번째 줄에 있는 ddl-auto : none 때문에 테이블이 생성이 안되는 것이었다! 게다가 정의하는 곳도 제대로 읽어보지도 않고 hiberate 부분을 중복되게 막 써둔 것이었다 이러면 yml을 사용하는 보람이 없는데.. 아무튼 여기서 한 3시간 정도 애먹은 것 같아서 힘들었다.. 그래도 여러가지 글들을 찾아보다 에러잘보는 팁도 얻어서 기분이 나쁘지만은 않다.
2. 두 번째는 메서드 네임드 쿼리 문제였다. 분명 이제 테이블 생성까지는 되는 것 같은데 또 에러가 났다. 메서드 이름은 findFirst2ByUserNameLikeOrderByIDDesc에서 UserName, ID 이렇게 정의해놓고 정작 Testy 클래스에는 ID가 아닌 id라고 정의를 해놨다..
@Entity
@Getter
@Setter
public class Testy {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "user_name")
private String userName;
}
============================================================================
수정후
============================================================================
@Entity
@Getter
@Setter
@Table(name = "testy")
public class Testy {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_code")
private Integer ID;
@Column(name = "user_name")
private String userName;
}
private long id <-- 이렇게 적어놨다 이러니 쿼리랑 달라서 당연히 오류가 나지.. 테이블 어노테이션과 컬럼 어노테이션은 문제해결을 위해 발버둥친 흔적이다ㅎ;
@Repository
public interface TestyRepository extends JpaRepository<Testy, Integer> {
List<Testy> findFirst2ByUserNameLikeOrderByIDDesc(String name);
}
이렇게 하니 에러 문구가 살짝 달라지는 것을 느낄 수 있었다
Hibernate:
insert
into
testy
(user_name)
values
(?)
returning user_code
2024-06-06T21:10:21.873+09:00 WARN 50340 --- [projecttry] [ Test worker] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 42000, SQLState: 42000
2024-06-06T21:10:21.873+09:00 ERROR 50340 --- [projecttry] [ Test worker] o.h.engine.jdbc.spi.SqlExceptionHelper : Syntax error in SQL statement "insert into testy (user_name) values (?) [*]returning user_code"; SQL statement:
insert into testy (user_name) values (?) returning user_code [42000-224]
could not prepare statement [Syntax error in SQL statement "insert into testy (user_name) values (?) [*]returning user_code"; SQL statement:
3. 세 번째 문제코드
org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement [Syntax error in SQL statement "insert into testy (user_name) values (?) [*]returning user_code"; SQL statement:
chatgpt의 문제해결 제안
"returning user_code" 구문이 PostgreSQL에서 발생하는 문제와 관련이 있습니다. PostgreSQL에서 generated by default as identity를 사용할 때, Hibernate가 "returning" 구문을 적절히 처리하지 못할 때 발생합니다. 이를 해결하기 위해 몇 가지 방법을 제안합니다.
GenerationType.IDENTITY 대신 GenerationType.SEQUENCE 사용
먼저, @GeneratedValue 어노테이션을 GenerationType.SEQUENCE로 변경하여 시퀀스를 사용하도록 설정할 수 있습니다. PostgreSQL에서 시퀀스는 더 잘 지원됩니다.
왜그런지 모르겠지만 returning 구문을 적절히 처리하지 못한다니..
Testy 클래스의 @GeneratedValue 의 Strategy 문제였다! Testy클래스에서 ID로 정의한(user_code) 컬럼은 자동생성되는 컬럼으로 @Id,@GeneratedValue 두개의 어노테이션이 필요했는데 여기서 나는 Strategy가 무슨역할을 하는지도 모르고 냅다 쓰기만 해서 문제가 발생된거였다..
GenerationType.IDENTITY와 GenerationType.SEQUENCE의 차이점
주요 차이점 요약
- 키 생성 방식:
- IDENTITY: 데이터베이스의 자동 증가 기능을 사용.
- SEQUENCE: 데이터베이스의 시퀀스 객체를 사용.
- 퍼포먼스 및 트랜잭션:
- IDENTITY: 데이터 삽입 시 키가 생성되므로, 삽입 전에 키 값을 알 수 없음.
- SEQUENCE: 데이터 삽입 전에 키 값을 미리 가져올 수 있음.
- 데이터베이스 종속성:
- IDENTITY: 키 생성이 데이터베이스에 의존적.
- SEQUENCE: 시퀀스 객체를 지원하는 데이터베이스에서 사용 가능.
이거 까지 수정해서 결국 테스트 성공..
하아 오늘 해결 못할 줄 알았는데 해결해서 너무 다행이다
문제 해결 능력 키우는 방법
출처:https://kth990303.tistory.com/423
'Error 정리' 카테고리의 다른 글
[Junit Test] 테스트가 안될때 (0) | 2024.09.04 |
---|---|
상태코드 405 서버 오류 (Postman 사용) (0) | 2024.06.20 |
[gradle.kts]Spring Boot & React 연동 에러 (1) | 2024.06.07 |