-
카테고리
-
세부 분야
백엔드
-
해결 여부
해결됨
update에서 new BeanPropertySqlParameterSource()사용시 문제
24.05.12 23:34 작성 조회수 81
0
강의에서 update부분을
new BeanPropertySqlParameterSource()
로 변경해서 사용해 보았는데 수정이 정상적을 이루어 졌습니다.
I’d가 어떻게 자동으로 매핑이 되는건가요?
답변을 작성해보세요.
0
OMG
2024.05.13
안녕하세요. 양치잘하기님, 공식 서포터즈 OMG입니다.
강의 코드를 변경하셨다면 어떻게 변경했는지 알아야 확인 후 답변을 드릴 수 있습니다 😀
MapSqlParameterSource() 대신 BeanPropertySqlParameterSource()를 사용한게 맞을까요? 파라미터로 받아오는 itemId와 sql 처리가 어떻게 되었는지 등 전반적인 update()코드와 관련된 클래스 중 강의와 다르게 직접 작성한 코드가 있다면 같이 첨부해주시겠어요?
감사합니다.
양치잘하기
질문자2024.05.13
@Slf4j
public class JdbcTemplateItemRepositoryV2 implements ItemRepository {
// private final JdbcTemplate template;
private final NamedParameterJdbcTemplate template; // 파라미터 바인딩을 순서가 아닌 이름으로 하게 해줌
public JdbcTemplateItemRepositoryV2(DataSource dataSource) {
this.template = new NamedParameterJdbcTemplate(dataSource);
}
@Override
public Item save(Item item) {
String sql = "insert into item(item_name, price, quantity) " +
"values (:item_name, :price, :quantity)";
// 이름기반의 파라미터가 필요
// item객체의 필드들을 이름으로 파라미터를 만든다
// SqlParameterSource param = new BeanPropertySqlParameterSource(item);
Map<String, Object> param = Map.of(
"item", item.getItemName(),
"price", item.getPrice(),
"quantity", item.getQuantity()
);
KeyHolder keyHolder = new GeneratedKeyHolder();
template.update(sql, (SqlParameterSource) param, keyHolder);
long key = keyHolder.getKey().longValue();
item.setId(key);
return item;
}
@Override
public void update(Long itemId, ItemUpdateDto updateParam) {
String sql = "update item set item_name = :item_name, price = :price, quantity = :quantity where id = :id";
// SqlParameterSource param = new MapSqlParameterSource()
// .addValue("itemName", updateParam.getItemName())
// .addValue("price", updateParam.getPrice())
// .addValue("quantity", updateParam.getQuantity())
// .addValue("id", itemId);
SqlParameterSource param = new BeanPropertySqlParameterSource(updateParam);
template.update(sql, param);
}
@Override
public Optional<Item> findById(Long id) {
String sql = "select id, item_name, price, quantity from item where id = :id";
try {
Map<String, Object> param = Map.of("id", id);
// SqlParameterSource param = new BeanPropertySqlParameterSource(id);
Item item = template.queryForObject(sql, param, itemRowMapper());
return Optional.of(item);
} catch (EmptyResultDataAccessException e) {
return Optional.empty();
}
}
@Override
public List<Item> findAll(ItemSearchCond cond) {
Integer maxPrice = cond.getMaxPrice();
String itemName = cond.getItemName();
SqlParameterSource param = new BeanPropertySqlParameterSource(cond);
String sql = "select id, item_name, price, quantity from item";
//동적 쿼리
if (StringUtils.hasText(itemName) || maxPrice != null) {
sql += " where";
}
boolean andFlag = false;
if (StringUtils.hasText(itemName)) {
sql += " item_name like concat('%',:itemName,'%')";
andFlag = true;
}
if (maxPrice != null) {
if (andFlag) {
sql += " and";
}
sql += " price <= :maxPrice";
} log.info("sql={}", sql);
return template.query(sql, param, itemRowMapper());
}
private RowMapper<Item> itemRowMapper() {
// return (rs, rowNum) -> {
// Item item = new Item();
// item.setId(rs.getLong("id"));
// item.setItemName(rs.getString("item_name"));
// item.setPrice(rs.getInt("price"));
// item.setQuantity(rs.getInt("quantity"));
// return item;
// };
return BeanPropertyRowMapper.newInstance(Item.class); //camel 변환 지원
}
}
해당 코드를 실행하였습니다.
첫 실행시 아이템 이름을 수정하니
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Mon May 13 13:24:51 KST 2024
There was an unexpected error (type=Internal Server Error, status=500).
로 이동하여 수정이 안되는데 같은 아이템의 가격, 수량을 수정하는것은 정상적으로 동작합니다.
1, 2번 아이템이 특히 이렇게 동작하였고 나머지 아이템들은 이름, 가격, 수량을 수정하여도 정상적으로 반영이 됩니다.
양치잘하기
질문자2024.05.13
아 제가 Config에 빈 등록할때 리포지토리를 V2로 안바꾸고 실행해서 적용이 안되었던거였네요 ;;; ㅎㅎV2로 변경하고 나니 오류 발생합니다.
그런데 강의자료로 올려주신pdf에는 V2에 @Repository어노테이션에 붙어있는데
개발자가 직접 빈 등록을 하였으면 @Repository 어노테이션이 필요 없는것 아닌가요? 영상에서는 안 붙여 주셨는데 강의자료에 따로 붙어있는 이유가 있나요?
그리고 h2데이터베이스 클라이언트에서 item테이블의 튜플들을 모두 지우고 서버를 다시 시작했는데 id가 1번부터 시작하지 않고 지우기전 id의 다음순서의 id로 시작을 하는데 id는 왜 1번부터 시작하지 않는건가요? 1번부터 시작하게 하려면 어떻게 해야하나요?
OMG
2024.05.15
예리한 질문이십니다 😀
@Repository를 사용하면 JDBC 예외를 스프링의 데이터 계층 예외로 변환해주는 AOP가 적용되는데요, JdbcTemplate은 JDBC 예외를 스프링의 데이터 계층 예외로 변환해주는 기능을 내부에 포함하고 있어서 사용하지 않았다고 하시네요.
메뉴얼과의 차이는 잘 모르겠습니다.
https://www.inflearn.com/questions/1211018/repository-%EC%82%AC%EC%9A%A9-%EC%B0%A8%EC%9D%B4%EC%A0%90
h2 시퀀스를 초기화 하는 방법은 다음 링크를 참고해주세요^^
답변 1