executeAndReturnKey
[Spring] SimpleJdbcInsert 사용 시 테이블이나 칼럼을 제대로 불러오지 못할 때 해결 방법
문제 발생
JDBC로 insert를 구현하던 중에 에러를 만났다.
우선 코드는 아래와 같다.
@RequiredArgsConstructor
@Repository
public class MemberRepository {
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
...
private Member insert(Member member) {
SimpleJdbcInsertOperations simpleJdbcInsert =
new SimpleJdbcInsert(namedParameterJdbcTemplate.getJdbcTemplate())
.withTableName("Member") // INSERT INTO 'TABLE'
.usingGeneratedKeyColumns("id"); // AUTO_INCREMENT
SqlParameterSource params = new BeanPropertySqlParameterSource(member);
long id = simpleJdbcInsert
.executeAndReturnKey(params)
.longValue();
return Member
.builder()
.id(id)
.email(member.getEmail())
.nickname(member.getNickname())
.birthDay(member.getBirthDay())
.createdAt(member.getCreatedAt())
.build();
}
}
▲ Member의 Id 칼럼을 PK로 하여 Auto_increment를 설정해서 insert하기위한 Method
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://${LOCAL_DB_URL}?rewriteBatchedStatements=true&characterEncoding=UTF-8&serverTimezone=Asia/Seoul
username: ${LOCAL_DB_USERNAME}
password: ${LOCAL_DB_PASSWORD}
▲ application.yml의 Datasource 설정
LOCAL_DB_URL=localhost:3306/fast_sns
▲ 환경 변수
해당 코드를 실행하면 아래와 같은 에러가 발생한다.
java.sql.SQLSyntaxErrorException: Unknown column 'member_id' in 'field list'
??????
내가 생성한 Column 중에 member_id는 존재하지 않는데 member_id를 왜 찾지??
원인
그래서 위쪽을 보니 아래와 같은 실행 구문이 있었다.
Retrieving meta-data for testdb2/root@localhost/member
...
Compiled insert object: insert string is [INSERT INTO Member (member_id, created_at, last_modified_at, about, email, member_status, nick_name, password, picture_url, profile_id) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]
SimpleJdbcInsert가 현재 프로젝트에 연동된 DB가 아닌 다른 DB의 Member 테이블을 찾아서 로직을 실행하는 것 같았다.
그래서 SimpleJdbcInsert 공식 문서를 통해 관련 내용을 찾아보았다.
SimpleJdbcInsert는 테이블에 대한 쉬운 삽입 기능을 제공한다.
기본 삽입문을 구성하는데 필요한 코드를 단순화하기 위해 메타데이터 처리를 제공한다.
그러니까 테이블 이름과 열 이름, 열 값이 포함된 Map만 제공하면 된다.
메타데이터 처리는 JDBC Driver에서 제공하는 DatabaseMetaData를 기반으로 한다.
JDBC Driver가 지정된 테이블의 열 이름을 제공할 수 있는 한 자동 탐지 기능을 사용할 수 있다.
쉽게 말해 withTableName()을 통해서 제공된 테이블 명을 통해 자동으로 탐지한다는 것 같다.
그렇다면 공식 문서를 참고해 withSchemaName()이나 withCatalogName()을 활용해서 해결해보기로 했다.
해결
StackOverflow를 통해 Catalog와 Schema의 차이를 파악해서 withCatalogName()을 사용해 DB명을 지정해주었더니 문제가 해결되었다.
@RequiredArgsConstructor
@Repository
public class MemberRepository {
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
private Member insert(Member member) {
SimpleJdbcInsertOperations simpleJdbcInsert =
new SimpleJdbcInsert(namedParameterJdbcTemplate.getJdbcTemplate())
.withCatalogName("fast_sns") // 추가된 부분 (DB명 지정)
.withTableName("Member") // INSERT INTO 'TABLE'
.usingGeneratedKeyColumns("id"); // AUTO_INCREMENT
SqlParameterSource params = new BeanPropertySqlParameterSource(member);
long id = simpleJdbcInsert
.executeAndReturnKey(params)
.longValue();
return Member
.builder()
.id(id)
.email(member.getEmail())
.nickname(member.getNickname())
.birthDay(member.getBirthDay())
.createdAt(member.getCreatedAt())
.build();
}
}
참고 자료
[Velog@lango - Kakao Cloud School 10번째 회고록]
[StackOverflow - What`s the difference between a catalog and a schema in a relational database?]
'Spring' 카테고리의 다른 글
[Spring/Thymeleaf] 세션 방식 로그인 및 템플릿 구현 (0) | 2023.08.29 |
---|---|
[Spring/Error] WebSecurityCustomizer를 통해 정적 자원에 대한 Ignore가 안될때 (0) | 2023.08.28 |
[Spring] 다중 칼럼 인덱스를 활용한 쿼리 속도 개선 (0) | 2023.05.14 |
[Spring] Scheduler(@Scheduled)를 활용한 마감 시간 관리 (0) | 2023.03.23 |
[Spring] Postman 404, 405 Error (0) | 2022.10.24 |