[요약]
- DB를 활용해서 SQL문을 JAVA 언어로 사용할 수 있다.
1. JDBC Template 정의
- GoF의 디자인 패턴 중 템플릿 디자인 패턴이 적용된 클래스
- 템플릿 디자인 패턴: 반복되는 작업을 캡슐화하여 재사용할 수 있는 패턴으로 정의하는 방식
- DBCP(DataBase Connection Pool)에 DataSource(DB 연결 정보 객체)을 의존성으로 주입받아서
커넥션의 풀을 구성하고 커넥션들을 계속 대여하여 재사용할 수 있는 방식
[결론] 이걸 왜하냐?
try~catch~finally 구문을 할 필요 없이 JDBC Template를 이용하여 계속 사용
2. JDBC Template 사용가능 메소드
[1번 방식] update(): insert, update, delete 쿼리 실행
update(쿼리문, 물음표인자값1, 물음표인자값2, 물음표인자값3);
[2번 방식] 물음표 인자 개수만큼 배열을 생성하여 배열 자체를 매개변수로 보내는 방식
Object[] args = {물음표인자값1, 물음표인자값2, 물음표인자값3};
update(쿼리문, args);
[다른 메소드]
queryForInt() : 결과값이 정수(sum, count, avg)
queryForObject() : RowMapper라는 인터페이스를 상속받아 구현한 클래스를 리턴
mapRow() 라는 메소드를 구현해서 개별자가 원하는 형태의 객체로 만들어 리턴
query() : 다중행일때 사용. 사용법은 queryForObject()와 동일.
3. db.properties 파일 작성
* jdbc 연결을 외부 파일로 작성하여 가져오는 방식으로 시행
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/studydb?serverTimezone=UTC
jdbc.username=(설정한 id)
jdbc.password=(설정한 비밀번호)
4. root-context.xml 수정
가. JDBC 연결을 위한 객체 생성
나. JDBC Template bean 객체 등록
<!--외부 파일 참조-->
// classpath: main에 있는 폴더를 찾게 됨
<context:property-placeholder location="classpath:/config/db.properties"/>
<!--라이브러리(jar 파일)의 클래스에는 어노테이션을 달 수 없기때문에 bean 엘리먼트를 통해서 bean 객체를 생성하고 등록한다.-->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
// ${}를 이용해서 외부파일(db.properties)에서 key값을 가져옴.
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--JDBC Template bean 객체 등록-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
5. pom.xml : JDBC Template bean 객체 등록(MVN REPOSITORY 사이트 검색)
<!--JDBC Template 의존성 주입-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
6. BoardRowMapper 클래스 생성
- RowMapper 인터페이스 상속
- mapRow 메소드 구현 -> 개발자가 원하는 형태의 객체로 만들어 리턴
public class BoardRowMapper implements RowMapper<BoardDto> {
@Override
public BoardDto mapRow(ResultSet rs, int rowNum) {
BoardDto boardDto = new BoardDto();
try {
boardDto.setId(rs.getInt("ID"));
boardDto.setTitle(rs.getString("TITLE"));
boardDto.setContent(rs.getString("CONTENT"));
boardDto.setWRITER_ID(rs.getInt("WRITER_ID"));
boardDto.setNickname(rs.getString("NICKNAME"));
boardDto.setRegdate(rs.getTimestamp("REGDATE").toInstant().atZone(ZoneId.of("UTC")).toLocalDateTime());
boardDto.setModdate(rs.getTimestamp("MODDATE").toInstant().atZone(ZoneId.of("UTC")).toLocalDateTime());
boardDto.setCnt(rs.getInt("CNT"));
} catch(SQLException se) {
System.out.println(se.getMessage());
}
return boardDto;
}
7. JDBC Template 구현방법 (2가지)
가. JdbcDaoSuppor 상속
나. JdbcTemplate 필드 선언
2가지 방법의 차이점
1. JdbcDaoSupport는 DAO 클래스를 작성할 때 JdbcTemplate을 쉽게 사용할 수 있도록 도와주는 추상 클래스입니다.
이 두 가지를 적절하게 사용하면 Spring 환경에서 효율적으로 데이터베이스 작업을 수행할 수 있습니다.
2. JdbcTemplate은 직접 JDBC 작업을 간편하게 처리할 수 있는 도구입니다.
① : JdbcDaoSupport 클래스 상속받아 사용 -> "2. JDBC Template 사용가능 메소드" 참고
- 리턴값이 없을 때: getJdbcTemplate().update(쿼리문, 물음표인자값..)
- 리턴값이 List일때: boardDtoList = getJdbcTemplate().query(쿼리문, new BoardRowMapper());
- 리턴값이 단행문일때: boardDto = getJdbcTemplate().queryForObject(쿼리문, args, new BoardRowMapper());
* 중요: queryForObject에서 args 매개변수를 사용할 때는 Object 배열 형태여야 한다.
-> Object[] args = {id};
@Repository
// JdbcDaoSupport 상속
public class FreeBoardDaoJdbcDaoSupport extends JdbcDaoSupport {
// setSuperDataSource 메서드 사용
@Autowired
public void setSuperDataSource(DataSource dataSource) {
super.setDataSource(dataSource);
}
(쿼리문 동일)...
public void post(BoardDto boardDto) {
System.out.println("FreeBoardDao의 post 메소드 실행");
getJdbcTemplate().update(POST, boardDto.getTitle(), boardDto.getContent(), boardDto.getWRITER_ID());
System.out.println("FreeBoardDao의 post 메소드 실행 종료");
}
public void modify(BoardDto boardDto) {
System.out.println("FreeBoardDao의 modify 메소드 실행");
getJdbcTemplate().update(MODIFY, boardDto.getTitle(), boardDto.getContent(), boardDto.getModdate().toString(), boardDto.getId());
System.out.println("FreeBoardDao의 modify 메소드 실행 종료");
}
public List<BoardDto> getBoardList() {
System.out.println("FreeBoardDao의 getBoardList 메소드 실행");
List<BoardDto> boardDtoList = new ArrayList<>();
boardDtoList = getJdbcTemplate().query(GET_BOARD_LIST, new BoardRowMapper());
System.out.println("FreeBoardDao의 getBoardList 메소드 실행 종료");
return boardDtoList;
}
public void delete(int id) {
System.out.println("FreeBoardDao의 delete 메소드 실행");
getJdbcTemplate().update(DELETE, id);
System.out.println("FreeBoardDao의 delete 메소드 실행 종료");
}
public BoardDto getBoard(int id) {
System.out.println("FreeBoardDao의 getBoard 메소드 실행");
BoardDto boardDto = new BoardDto();
// queryForObject의 두 번째 매개변수는 Object 배열 형태여야한다.
Object[] args = {id};
boardDto = getJdbcTemplate().queryForObject(GET_BOARD, args, new BoardRowMapper());
System.out.println("FreeBoardDao의 getBoard 메소드 실행 종료");
return boardDto;
}
- 결과
② : JdbcTemplate을 필드로 선언하고 의존성을 주입받아서 사용하는 방식
- JdbcTemplate 필드 선언
- 리턴값이 없을 때: jdbcTemplate().update(쿼리문, 물음표인자값..)
- 리턴값이 List일때: boardDtoList = jdbcTemplate().query(쿼리문, new BoardRowMapper());
- 리턴값이 단행문일때: boardDto = jdbcTemplate().queryForObject(쿼리문, args, new BoardRowMapper());
* 중요: queryForObject에서 args 매개변수를 사용할 때는 Object 배열 형태여야 한다.
-> Object[] args = {id};
@Repository
public class FreeBoardDao {
private JdbcTemplate jdbcTemplate;
@Autowired
public FreeBoardDao(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
... 쿼리 동일
public void post(BoardDto boardDto) {
System.out.println("FreeBoardDao의 post 메소드 실행");
jdbcTemplate.update(POST, boardDto.getTitle(), boardDto.getContent(), boardDto.getWRITER_ID());
System.out.println("FreeBoardDao의 post 메소드 실행 종료");
}
public void modify(BoardDto boardDto) {
System.out.println("FreeBoardDao의 modify 메소드 실행");
jdbcTemplate.update(MODIFY, boardDto.getTitle(), boardDto.getContent(), boardDto.getModdate().toString(), boardDto.getId());
System.out.println("FreeBoardDao의 modify 메소드 실행 종료");
}
public List<BoardDto> getBoardList() {
System.out.println("FreeBoardDao의 getBoardList 메소드 실행");
List<BoardDto> boardDtoList = new ArrayList<>();
boardDtoList = jdbcTemplate.query(GET_BOARD_LIST, new BoardRowMapper());
System.out.println("FreeBoardDao의 getBoardList 메소드 실행 종료");
return boardDtoList;
}
public void delete(int id) {
System.out.println("FreeBoardDao의 delete 메소드 실행");
jdbcTemplate.update(DELETE, id);
System.out.println("FreeBoardDao의 delete 메소드 실행 종료");
}
public BoardDto getBoard(int id) {
System.out.println("FreeBoardDao의 getBoard 메소드 실행");
BoardDto boardDto = new BoardDto();
// queryForObject의 두 번째 매개변수는 Object 배열 형태여야한다.
Object[] args = {id};
boardDto = jdbcTemplate.queryForObject(GET_BOARD, args, new BoardRowMapper());
System.out.println("FreeBoardDao의 getBoard 메소드 실행 종료");
return boardDto;
}
'백엔드 > Spring Framework' 카테고리의 다른 글
AOP 에서 aspect와 advisor를 사용할 때의 차이점 / Joinpoint와 pointcut의 차이 (2) | 2024.07.14 |
---|---|
트랜잭션 처리 (0) | 2024.07.12 |
AOP(Aspect Oriented Programming) / 관점 지향 프로그래밍 / JoinPoiont 인터페이스 (0) | 2024.07.11 |
AOP(Aspect Oriented Programming) / 관점 지향 프로그래밍 / 동작 시점 (0) | 2024.07.11 |
AOP(Aspect Oriented Programming) / 관점 지향 프로그래밍 (0) | 2024.07.11 |