들어가기 전에
이번 시간엔 실습을 통해 Spring JDBC에 대해 알아보도록 하겠습니다.
학습 목표
- DTO와 DAO에 대한 개념을 이해합니다.
- Spring JDBC를 이용해 DAO를 작성할 수 있습니다.
핵심 개념
- DTO
- DAO
- NamedParameterJdbcTemplate
학습하기
들어가기 전에
이번 시간엔 실습을 통해 Spring JDBC에 대해 알아보도록 하겠습니다.
학습 목표
핵심 개념
학습하기
실습코드
RoleDaoSqls.java에 추가
public static final String UPDATE = "UPDATE role SET description = :description WHERE ROLE_ID = :roleId";
RoleDao.java
package kr.or.connect.daoexam.dao;
import static kr.or.connect.daoexam.dao.RoleDaoSqls.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Repository;
import kr.or.connect.daoexam.dto.Role;
@Repository
public class RoleDao {
private NamedParameterJdbcTemplate jdbc;
private SimpleJdbcInsert insertAction;
private RowMapper<Role> rowMapper = BeanPropertyRowMapper.newInstance(Role.class);
public RoleDao(DataSource dataSource) {
this.jdbc = new NamedParameterJdbcTemplate(dataSource);
this.insertAction = new SimpleJdbcInsert(dataSource)
.withTableName("role");
}
public int insert(Role role) {
SqlParameterSource params = new BeanPropertySqlParameterSource(role);
return insertAction.execute(params);
}
public int update(Role role) {
SqlParameterSource params = new BeanPropertySqlParameterSource(role);
return jdbc.update(UPDATE, params);
}
}
JDBCTest.java
package kr.or.connect.daoexam.main;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import kr.or.connect.daoexam.config.ApplicationConfig;
import kr.or.connect.daoexam.dao.RoleDao;
import kr.or.connect.daoexam.dto.Role;
public class JDBCTest {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(ApplicationConfig.class);
RoleDao roleDao = ac.getBean(RoleDao.class);
Role role = new Role();
role.setRoleId(201);
role.setDescription("PROGRAMMER");
int count = roleDao.insert(role);
System.out.println(count + "건 입력하였습니다.");
int count = roleDao.update(role);
System.out.println(count + " 건 수정하였습니다.");
}
}
참고 자료
https://www.tutorialspoint.com
https://ejbvn.wordpress.com
comment
20.06.15
sql에서 _ (스네이크)로 정의된 속성을 스프링에서 매칭할땐 _ 뒤의 첫번째 글자는 대문자로하고 _는 없에서 지정해줘야 하는것 맞나요?
같은 타입의 인자 값을 2개이상 전달 받는 경우, JDBCTemplate은 파라미터 전달 순서에 따라 조회 결과가 달라질 수 있지만, NameParameterJdbcTemplate을 사용하면 명시적으로 조건에 맞는 컬럼에 데이터가 바인딩 되기 때문에 휴먼에러를 줄일 수 있다는 장점이 있다고 생각합니다.
이게 잘 이해가 안된다면
https://tte-yeong.tistory.com/69
참조해보세요 강의 그대로 올려서 복습하는 용도로도 괜찮네요
2번째 영상에서 오류 해결 :
1. private String url = "jdbc:mysql://localhost:3306/connectdb?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC";
2. cmd창이나 terminal창에서 mysql -V 치면 나오는 mysql 버전으로 pom.xml의 dependency 수정.
3. pom.xml 내 Spring version을 수정. google에 java spring context라고 쳤을 때 맨 처음 나오는 사이트 타고 들어가면 나오는 버전 정보 중 맨 위에 있는 것 (5.2.5.RELEASE 같은)
mysql 현재 기준으로 8.0.19 버전 사용 하시는 분들은
private final String DRIVER = "com.mysql.cj.jdbc.Driver";
이 코드를 사용 하시면 됩니다.
private final String DRIVER = "com.mysql.cj.jdbc.Driver";
private final String URL = "jdbc:mysql://localhost:3306/데이터베이스 명?serverTimezone=Asia/Seoul&useSSL=false&characterEncoding=utf8";
private final String USER = "로그인 할 계정";
private final String PASSWORD = "계정비밀번호";
RoleDao.ava 의
public List<Role> selectAll(){
return jdbc.query(SELECT_ALL, Collections.emptyMap(), rowMapper) <- query에서 오류나시는 분들
public List<Role> selectAll(){
return jdbc.query(SELECT_ALL, Collections.<String, Object>emptyMap(), rowMapper); 로 바꿔보세요. query인자가 바뀌었든, collections 메소드가 바뀌었든.. 이유는 모르지만 이렇게 하니까 되네요
Resource leak: 'ac' is never closed 경고 거슬리시는 분들은 윗줄에 @SuppressWarnings("resource") 추가하시면 무시됩니다
언제나 감사하게 강의 잘 듣고 있습니다! 생각해보기의 JdbcTemplate을 이용하지 않고 NamedParameterJdbcTemplate을 이용하는 이유는 쿼리문에 물음표 대신 구체적인 이름이 주어진 파라미터를 사용할 수 있게 함으로써, 예제처럼 SQL이 DAO 외의 다른 클래스나 파일에 저장되는 경우에 더 쉽게 일어날 수 있는 잘못된 순서로 값을 전달하거나 하는 실수를 줄일 수 있기 때문입니다.
private String driverClassName = "com.mysql.jdbc.Driver";
private String url = "jdbc:mysql://localhost:3306/connectdb?serverTimezone=Asia/Seoul&useSSL=false&characterEncoding=utf8";
private String username = "connectuser";
private String password = "connect123!@#";
궁금한게 있습니다! 제가 컬럼을 role_id로 해놓고 DTO에서는 roleID 이렇게 입력했더니 null값이 들어가서 오류가 났습니다. roleId로 다시 만드니까 되네요?! 대소문자도 구분을 하나요??
마이바티스 없이 작업하니 헷갈려서 여러번 반복해봐야겠네요
후 어려웠네요 감사합니다!
코드를 똑같이 했는데 오류가 나서 아래와 같이 해결했습니다.
1. pom.xml에 spring 버전과 mysql-connector 버전이 충분히 최신인지 확인,
옛날 거면 최신 것으로 변경
2. DBConfig.java에 url을 수정해준다.
private String url = "jdbc:mysql://localhost:3306/connectdb?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC"; 처럼 뒤에 타임존 명시
분명 똑같이 했는데 오류가 나길래 뭐 때문일까 했는데, 버전을 고치니 해결됐습니다. AnnotationConfigApplicationContext에서 오류나던 건 spring 버전 고치고, JDBC 드라이버 로드 오류나던 건 mysql-connector 버전 고치고 해결했습니다.
아무래도 강의 올라오는 시점보다 좀 많이 늦게 보는 거라, 버전 확인 잘 해야될 거 같습니다. 각자 환경에 맞게 버전을 잘 설정해야 된다는 걸 다시 느끼네요ㅜㅜ 똑같이 했는데 오류나시는 분 계시면 버전 고쳐보세요.
insert만 roleDao 생성자에서 따로
이렇게 만들어서 insert 메서드안에서 이렇게 콜하는 이유가 있을까요?
update에서 했던 방법(아래)처럼 해도 작동은 하네요
오류나실때 import 부분이 제공되는 코드랑 완전히 같은지 확인하시면 좋은 것 같습니다.
EnableTransactionManagement annotation import가 안됩니다.
spring-tx.jar 에 transaction.annotation package안에 class가 있는 것 까지 확인이 됐는데 왜그런지 모르겠습니다.
public List<Role> selectAll(){
return jdbc.query(SELECT_ALL, Collections.emptyMap(), rowMapper);
}
query부분에서 오류납니다.
감사합니다.