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?]

+ Recent posts