인프런 커뮤니티 질문&답변

shanePark님의 프로필 이미지

작성한 질문수

스프링 DB 2편 - 데이터 접근 활용 기술

JdbcTemplate - 이름 지정 파라미터 3

KeyHolder가 데이터베이스에 따라 다르게 동작할까요?

해결된 질문

작성

·

657

1

안녕하세요 :)
 
    @Override
public Item save(Item item) {
String sql = "insert into item(item_name, price, quantity)" +
" values (:itemName,:price,:quantity)";

BeanPropertySqlParameterSource param = new BeanPropertySqlParameterSource(item);

KeyHolder keyHolder = new GeneratedKeyHolder();
template.update(sql, param, keyHolder);

long id = keyHolder.getKey().longValue();
item.setId(id);
return item;
}
 
save 메서드를 강의대로 했을때 저는 InvalidDataAccessApiUsageException 이 발생 하더라고요.
 
org.springframework.dao.InvalidDataAccessApiUsageException: The getKey method should only be used when a single key is returned. The current key entry contains multiple keys: [{id=7, item_name=productE, price=50000, quantity=20}]
 
그래서 id 를 받아 오는 부분을
```java
Long id = (Long) keyHolder.getKeys().get("id");
```
key를 받아오고 id 를 빼는 식으로 변경 했더니 잘 동작 합니다.
혹시나 해서 테이블을 확인 했는데 primary key 설정도 되어 있는 상태 입니다.
강의를 회사에 일찍 출근해서도 듣고 집에 퇴근하고 와서도 듣다보니 연속성을 위해 PostgresDB를 따로 구축해두고 사용하고 있는데 .. 혹시나 해서 H2 로 변경 해서 테스트 해 보니 getKey() 만 해도 정상적으로 동작 되었습니다.
KeyHolder의 getKey가 DB에 따라 상이하게 동작하는걸까요..?
 
update 파라미터를 우연히 보았더니 keyColumn 을 파라미터로 받길래
 
혹시나 해서 "id" 를 넣었더니, 이 때에도 getKey()가 정상적으로 동작 하였습니다.
 
우연히 해결을 하기는 했는데 KeyHolder의 작동 원리에 대한 이해가 없다보니 궁금하네요..
 
1. DB 에 테이블을 등록할 때 제가 뭔가 누락한게 있어서 그럴까요? 아니면 단순히 Postgres 를 사용해서 그런 걸까요?
2. DB에 따라 getKey()가 안될 수 있다면, getKeys() 후에 원하는 key를 받아오는 것과 update 할 때에 key column을 명시해 주는 것 중 어느쪽이 더 명확할까요? 혹은 더 나은 방법이 있을까요?
 
감사합니다
 

답변 2

2

OR님의 프로필 이미지

2022. 11. 27. 22:17

저도 마찬가지로 postgresql로 진행하다가 같은 문제를 만나서, getKeys() 로 맵을 받은 후, 그곳에서 id를 가져오는 방식을 사용했습니다.

혹시나 해서 질문란을 오니 역시나 훌륭한 답변이 있었군요. 전 이 글을보고 key column을 명시해 주는 방향이 낫다고 생각해서 이 방법으로 변경하였습니다.

왜냐하면 그렇게 해야 아주 조금이라도 서버-DB간 주고 받는 데이터가 줄어들지 않나 싶었습니다.

key column을 명시하지 않은 경우:

  • 서버에 쿼리 날릴 때 키 컬럼 어레이 부분을 보내지 않음.

  • 하지만 DB에서 보내오는 keyHolder 값에 모든 컬럼의 값이 포함. (id, item_name, price, quantity)

key column을 명시한 경우:

  • 서버에 쿼리 날릴 때 키 컬럼 어레이 new String[]("id)를 포함.

  • 대신 DB에서 보내오는 keyHolder 값에 id 컬럼 값만 포함.

엔티티의 컬럼 값이 늘어날수록, 두 경우의 데이터 전송량의 차이는 더 늘어날 것 같습니다.

2

김영한님의 프로필 이미지
김영한
지식공유자

2022. 06. 20. 18:55

안녕하세요. shane님

이 부분은 저도 정확히 잘 모르겠습니다. 혹시 아시는 분 있으면 답변 부탁드려요.

감사합니다.

YG K님의 프로필 이미지

2022. 07. 11. 23:00

https://shanepark.tistory.com/383

후에 블로그에 작성해 두셨네요

김영한님의 프로필 이미지
김영한
지식공유자

2022. 07. 17. 13:04

공유 감사합니다^^