You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
JdbcTemplateItemRepositoryV1 은 ItemRepository 인터페이스를 구현했다.
this.template = new JdbcTemplate(dataSource)
JdbcTemplate 은 데이터소스( dataSource )가 필요하다.
JdbcTemplateItemRepositoryV1() 생성자를 보면 dataSource 를 의존 관계 주입 받고 생성자 내부에서 JdbcTemplate 을 생성한다. 스프링에서는 JdbcTemplate 을 사용할 때 관례상 이 방법을 많 이 사용한다.
물론 JdbcTemplate 을 스프링 빈으로 직접 등록하고 주입받아도 된다.
Save()
데이터를 변경할떈 template.update() 를 사용
즉 Insert, Update, Delete 에서 사용.
반환값은 int 인데 영향받은 로우 수
데이터 저장시 PK 생성에 idantity (자동 증가) 방식을 사용하기 떄문에, PK인 ID 값을 개발자가 지정하는것이 아니라 비우고 저장해야함. 그럼 데이터베이스가 ID 대신 생성함.
이러면 데이터 생성 완료 될 때 까지 ID 값을 모름. 그래서 insert 완료 후 꺼내와야함.
KeyHolder와connection.prepareStatement(sql, new String[]{"id"})를 사용해서id를 지정해주면INSERT` 쿼리 실행 이후에 데이터베이스에서 생성된 ID 값을 조회할 수 있다.
순수 JDBC 로도 가능한데 복잡함.
참고로 뒤에서 설명하겠지만 JdbcTemplate이 제공하는 SimpleJdbcInsert 라는 훨씬 편리한 기능이 있으 므로 대략 이렇게 사용한다 정도로만 알아두면 된다.
update()
template.update() 사용.
? 에 바인딩할 파라미터를 순서대로 전달하면 된다. 순서가 바뀌면 큰일남.
반환값은해당쿼리의영향을받은로우수이다.여기서는 where id=? 를 지정했기 때문에 영향 받은 로우수는 최대 1개이다.
findById()
데이터 하나 조회
template.queryForObject()
결과 로우가 하나일 때 사용한다.
RowMapper 는 데이터베이스의 반환 결과인 ResultSet 을 객체로 변환한다.
결과가 없으면 EmptyResultDataAccessException 예외가 발생한다.
결과가 둘 이상이면 IncorrectResultSizeDataAccessException 예외가 발생한다.
ItemRepository.findById() 인터페이스는 결과가 없을 때 Optional 을 반환해야 한다. 따라서 결과가 없으면 예외를 잡아서 Optional.empty() 를 대신 반환하면 된다.
findAll()
데이터를 리스트로 조회. 검색 조건으로 적절한 데이터 찾기
template.query()
결과가 하나 이상일 때 사용 (하나일때도 사용 가능)
RowMapper는 데이터베이스의 반환 결과인ResultSet` 을 객체로 변환한다.
결과가 없으면 빈 컬렉션을 반환
동적 쿼리를 사용하는데 바로 다음에 볼 예정
itemRowMapper()
데이터베이스 조회 결과를 객체로 변환할 때 사용.
JDBC 직접 사용할 때 ResultSet 과 동일
차이가 있다면 다음과 같이 JdbcTemplate이 다음과 같은 루프를 돌려주고, 개발자는 RowMapper 를 구현해서 그 내부 코드만 채운다고 이해하면 된다.
while(resultSet이끝날때까지) {
rowMapper(rs, rowNum)
}
JdbcTemplate 적용2- 동적 쿼리 문제
findAll() 에서 어려운 부분이 사용자가 검색하는 값에 따라 실행하는 SQL 이 동적으로 달라져야 한다는 점.
예를 들어서 다음과 같다.
검색 조건이 없음
select id, item_name, price, quantity from item
상품명( itemName )으로 검색
select id, item_name, price, quantity from item
where item_name like concat('%',?,'%')
최대 가격( maxPrice )으로 검색
select id, item_name, price, quantity from item
where price <= ?
상품명( itemName ), 최대 가격( maxPrice ) 둘다 검색
select id, item_name, price, quantity from item
where item_name like concat('%',?,'%')
and price <= ?
결과적으로 4가지 상황에 따른 SQL을 동적으로 생성해야 한다. 동적 쿼리가 언듯 보면 쉬워 보이지만, 막상 개발해보면 생각보다 다양한 상황을 고민해야 한다.예를 들어서 어떤 경우에는 where 를앞에넣고어떤경우에는 and 를 넣어야 하는지 등을 모두 계산해야 한다.
상황에 맞춰 파라미터도 생성
조건이 하나라도 더 있으면 훨씬 더 복잡해짐
직접 짜보면 버그가 안생길 수 없음...
참고로 이후에 설명할 MyBatis의 가장 큰 장점은 SQL을 직접 사용할 때 동적 쿼리를 쉽게 작성할 수 있다는 점이다.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
JdbcTemplate 소개와 설정
SQL 을 직접 사용하는 경우에 스프링이 제공하는 JdbcTemplate은 아주 좋은 선택지다. JdbcTemplate은 JDBC를 매우 편리하게 사용할 수 있게 도와준다.
장점
spring-jdbc)에 포함되어져 있기 때문에 복잡한 설정 없이 바로 사용 가능.statement를 준비하고 실행statement,resultset종료단점
설정하기
build.gradle에 아래 코드 추가.org.springframework.boot:spring-boot-starter-jdbc를 추가하면 JdbcTemplate이 들어있는spring-jdbc가 라이브러리에 포함된다.runtimeOnly 'com.h2database:h2'이거만 하면 끝. 추가 설정 없음.
H2 데이터베이스에 item 테이블 생성 필요
JdbcTemplate 적용1- 기본
기본
JdbcTemplateItemRepositoryV1은ItemRepository인터페이스를 구현했다.JdbcTemplate은 데이터소스(dataSource)가 필요하다.JdbcTemplateItemRepositoryV1()생성자를 보면dataSource를 의존 관계 주입 받고 생성자 내부에서JdbcTemplate을 생성한다. 스프링에서는JdbcTemplate을 사용할 때 관례상 이 방법을 많 이 사용한다.JdbcTemplate을 스프링 빈으로 직접 등록하고 주입받아도 된다.Save()
idantity(자동 증가) 방식을 사용하기 떄문에, PK인 ID 값을 개발자가 지정하는것이 아니라 비우고 저장해야함. 그럼 데이터베이스가 ID 대신 생성함.와connection.prepareStatement(sql, new String[]{"id"})를 사용해서id를 지정해주면INSERT` 쿼리 실행 이후에 데이터베이스에서 생성된 ID 값을 조회할 수 있다.SimpleJdbcInsert라는 훨씬 편리한 기능이 있으 므로 대략 이렇게 사용한다 정도로만 알아두면 된다.update()
?에 바인딩할 파라미터를 순서대로 전달하면 된다. 순서가 바뀌면 큰일남.where id=?를 지정했기 때문에 영향 받은 로우수는 최대 1개이다.findById()
template.queryForObject()RowMapper는 데이터베이스의 반환 결과인ResultSet을 객체로 변환한다.EmptyResultDataAccessException예외가 발생한다.IncorrectResultSizeDataAccessException예외가 발생한다.ItemRepository.findById()인터페이스는 결과가 없을 때Optional을 반환해야 한다. 따라서 결과가 없으면 예외를 잡아서Optional.empty()를 대신 반환하면 된다.findAll()
데이터를 리스트로 조회. 검색 조건으로 적절한 데이터 찾기
template.query()는 데이터베이스의 반환 결과인ResultSet` 을 객체로 변환한다.itemRowMapper()
데이터베이스 조회 결과를 객체로 변환할 때 사용.
JDBC 직접 사용할 때
ResultSet과 동일차이가 있다면 다음과 같이 JdbcTemplate이 다음과 같은 루프를 돌려주고, 개발자는
RowMapper를 구현해서 그 내부 코드만 채운다고 이해하면 된다.JdbcTemplate 적용2- 동적 쿼리 문제
findAll() 에서 어려운 부분이 사용자가 검색하는 값에 따라 실행하는 SQL 이 동적으로 달라져야 한다는 점.
예를 들어서 다음과 같다.
검색 조건이 없음
상품명(
itemName)으로 검색최대 가격(
maxPrice)으로 검색상품명(
itemName), 최대 가격(maxPrice) 둘다 검색결과적으로 4가지 상황에 따른 SQL을 동적으로 생성해야 한다. 동적 쿼리가 언듯 보면 쉬워 보이지만, 막상 개발해보면 생각보다 다양한 상황을 고민해야 한다.예를 들어서 어떤 경우에는
where를앞에넣고어떤경우에는and를 넣어야 하는지 등을 모두 계산해야 한다.상황에 맞춰 파라미터도 생성
조건이 하나라도 더 있으면 훨씬 더 복잡해짐
직접 짜보면 버그가 안생길 수 없음...
참고로 이후에 설명할 MyBatis의 가장 큰 장점은 SQL을 직접 사용할 때 동적 쿼리를 쉽게 작성할 수 있다는 점이다.
JdbcTemplate 적용3- 구성과 실행
코드가 동작하도록 구성하고 실행해보자.
컨피그로 빈 등록, 만든 리포지토리 사용
수정한 컨피그 파일 사용하도록 수정
데이터베이스 접근을 위한 설정 추가
지금부터 디비가 메모리기 아니기 때문에 서버 재시작 하면 그때 마다 테스트 데이터가 들어감.
로그 추가
JdbcTemplate이 실행하는 SQL 로그를 확인하려면
application.properties에 다음을 추가하면 된다.main,test설정이 분리되어 있기 때문에 둘다 확인하려면 두 곳에 모두 추가해야 한다.All reactions