능글맞은 구렁이
Spring-JDBC(Oracle) 본문
1. JdbcTemplate
*JdbcTemplate란? JDBC기반의 DB연동 프로그램을 쉽게 개발할 수 있도록 스프링에서 지원한 클래스
2. 스프링 JDBC설정
1] 라이브러리 추가 (pom.xml)
1) Spring JDBC 라이브러리
2). DBCP 라이브러리
2] JDBCUtil 클래스 만들기
1) JDBCUtil 클래스를 만들어 DAO클래스에 주입을 하면 DAO클래스의 SQL 메소드들은 일일이 JDBC연결 코드를
작성하지 않아도 된다.
3] DataSource설정
1) applicationContext.xml에 DataSource관련 <bean>을 등록한다.
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${데이터베이스드라이버}"></property>
<property name="url" value="${데이터베이스URL}"></property>
<property name="username" value="${접속계정아이디}"></property>
<property name="password" value="${접속계정비밀번호}"></property>
</bean>
2) 프로퍼티 파일을 활용한 Datasource설정
ㄱ) text에 JDBC에 관련된 코드를 작성해준다.
/**database.properties (text파일!)**/
jdbc.driver=드라이버
jdbc.url=데이터베이스URL
jdbc.username=접속계정아이디
jdbc.password=접속계정비밀번호
ㄴ) applicationContext.xml에 database.properties파일을 추가해준다.
/**applicationContext에 추가!**/
<!--property를 활용한 DataSource-->
<context:property-placeholder location="classpath:config/database.properties"/>
<!-- DataSource -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
※주의사항: database.properties의 명칭을 applicationContext.xml에서 그대로 사용해서 활용한다.
<!--1.번 pom.xml에 추가해준다.-->
<!-- Spring JDBC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- DBCP : DataBase Connection Poll -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
-----------------------------------------------------------------------------------------------
/**2.번 JDBCUtil 클래스 만들기**/
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JDBCUtil {
public JDBCUtil() {
}
/** 1. 데이터베이스 접속 객체 반환 메서드 **/
public static Connection getConnection() {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@127.0.0.1:1521:XE";
return DriverManager.getConnection(url, "board", "1234");
} catch (Exception e) {
System.err.println("JDBCUtile getConnection err:"+e.getMessage());
}
return null;
} // getConnection() END
/** 각 자원 해제 메서드 **/
// 1. PreparedStatement / Connection 해제
public static void close(PreparedStatement pstmt, Connection conn) {
if (pstmt != null) { // pstmt가 null이 아닐 경우
try {
if (!pstmt.isClosed()) { // pstmt가 닫혀(해제되어)있지 않을 경우
pstmt.close(); // pstmt를 닫기(자원 해제)
}
} catch (Exception e) {
System.err.println("JDBCUtill close pstmt err:" + e.getMessage());
} finally {
pstmt = null; // pstmt를 초기화
}
}
if (conn != null) {
try {
if (!conn.isClosed()) { conn.close();}
} catch (Exception e) {
System.err.println("JDBCUtill close conn err:" + e.getMessage());
} finally {conn = null;}
}
}
// 2. ResultSet / PreparedStatement / Connection 해제
public static void close(ResultSet rs, PreparedStatement pstmt, Connection conn) {
if (rs != null) {
try {
if (!rs.isClosed()) {rs.close();}
} catch (Exception e) {
System.err.println("JDBCUtill close rs err:" + e.getMessage());
} finally {pstmt = null;}
}
if (pstmt != null) {
try {
if (!pstmt.isClosed()) {pstmt.close();}
} catch (Exception e) {
System.err.println("JDBCUtill close pstmt err:" + e.getMessage());
} finally {pstmt = null; // pstmt를 초기화}
}
if (conn != null) {
try {
if (!conn.isClosed()) {conn.close();}
} catch (Exception e) {
System.err.println("JDBCUtill close conn err:" + e.getMessage());
} finally {conn = null;}
}
}
}
-----------------------------------------------------------------------------------------------
/**3번. config 패키지를 만들고 그안에 text파일로 저장**/
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:XE
jdbc.username=board
jdbc.password=1234
-----------------------------------------------------------------------------------------------
/**4번. applicationContext에 추가!**/
<!--property를 활용한 DataSource-->
<context:property-placeholder location="classpath:config/database.properties"/>
<!-- DataSource -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- Spring JDBC : jdbcTemplate의 메서드 사용을 위한 등록 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
3. JdbcTemplate메서드 사용 (스프링제공 , 빈태그 적용)
1)update( ) 메소드
SQL 구문 중 INSERT, UPDATE, DELETE 구문을 처리하기 위해 사용한다.
update() 메소드의 사용법은 '?'에 값을 설정하는 방식에 따라 크게 두 가지 형태로 있다.
ㄱ) SQL구문에 설정된 '?' 수만큼 값들을 차례대로 나열
메소드 : int update(String sql, Object...args)
예: public void updateBoard(BoardVO vo){
String BOARD_UPDATE="update board set title=?, content=? where seq=?";
int cnt=jdbcTemplate.update(BOARD_UPDATE, vo.getTitle(), vo.getContent(), vo.getSeq());
System.out.println(cnt+"건 데이터 수정);
}
ㄴ) Object 배열 객체에 SQL구문에 설정된 '?' 수만큼 값들을 세팅하여 배열 객체를 두번째 인자로 전달하는 방식
메소드 : int update(String sql, Object[] args)
예: public void updateBoard(BoardVO vo){
String BOARD_UPDATE="update board set title=?, content=? where seq=?";
Object[] args={vo.getTitle((), vo.getContent(), vo.getSeq()};
int cnt=jdbcTemplate.update(BOARD_UPDATE, args);
System.out.println(cnt+"건 데이터 수정);
}
2)queryForlnt( ) 메소드
SELECT구문으로 검색된 정숫값을 리턴받으려면 queryForInt() 메소드를 사용한다.
매개변수는 update( ) 메소드와 같다.
메소드 : int queryForInt(String sql)
int queryForInt(String sql, Object...args)
int queryForInt(String sql, Object[] args)
예: public int getBoardTotalCount(BoardVO vo){
String BOARD_TOT_COUNT="select count(*) from board";
int count=jdbcTemplate.queryForInt(BOARD_TOT_COUNT);
System.out.println("전체 게시글 수:"+count+"건");
}
3)queryForObject( ) 메소드
SELECT 구문의 실행 결과를 특정 자바 객체로 매핑하여 리턴받을 때 사용한다.
queryForObject() 메소드는 검색 결과가 없거나 검색 결과가 두개 이상이면 예외를 발생시킨다. 즉, 하나의
검색결과만 나와야하며 자바 객체로 매핑할 RowMapper객체를 반드시 지정해야한다.
( 필드명만 가져올때 많이 사용한다, RowMapper(interface)를 반드시 구현받아야 한다. )
메소드 : int queryForObject(String sql)
int queryForObject(String sql, RowMapper<T> rowMapper)
int queryForObject(String sql, Object[] args, RowMapper rowMapper)
예: public BoardVO getBoard(BoardVO vo){
String BOARD_GET="select * from board where seq=?";
Object[ ] args={ vo.getSeq( ) };
return jdbcTemplate.queryForObject(BOARD_GET, args, new BoardRowMapper());
}
※검색 결과를 특정 VO객체에 매핑하여 리턴하면 RowMapper 인터페이스를 구현한 RowMapper 클래스가
필요하다. 결국 , RowMapper 클래스는 테이블당 하나씩은 필요하다는 말이다. RowMapper 인터페이스에는
mapRow()메소드가 있어서 검색 결과로 얻어낸 Row정보를 어떤 VO에 어떻게 매핑할 것인지를 구현해주면 된다.
4)query( ) 메소드
SELECT문의 실행 결과가 목록일 때 사용한다. 기본 사용법은 queryForObject()메소드와 같다. 따라서
query( ) 메소드에서도 검색 결과를 VO객체에 매핑하려면 RowMapper 객체를 사용한다.
메소드 : int query(String sql)
int query(String sql, RowMapper<T> rowMapper)
int query(String sql, Object[] args, RowMapper rowMapper)
예: public List<BoardVO> getBoardList(BoardVO vo){
String BOARD_LIST="select * from board order by seq desc";
return jdbcTemplate.query(BOARD_GET, new BoardRowMapper());
}
※query( ) 메소드가 실행되면 여러 건의 ROW 정보가 검색되며, 검색된 데이터 ROW수만큼 RowMapper객체의
mapRow() 메소드가 실행된다. 그리고 이렇게 ROW정보가 매핑된 VO객체 여러개가 List 컬렉션에 저장되어
리턴된다. (전에 사용하던 if(rs.next()){ }, whlie(rs.next()){ }는 사용하지 않아도됨.)
5) RowMapper
RowMapper란? 원하는 형태의결과값을 반환할 수 있다. select로 나온 여러개의 값을 반환할 수 있을 뿐만아니라
사용자가 원하는 형태로도 얼마든지 받을 수 있다.
Class BoardRowMapper implements RowMapper<BoardVO>{
public BoardVO mapRow(ResultSet rs, int rowNum) throws SQLException{
BoardVO board=new BoardVO();
board.setTitle(rs.getString("title");
board.setWriter(rs.getString("writer");
board.setContent(rs.getString("content");
return board;
}
}
ResultSet에 값을 담아와서 board객체에 저장한다. 그리고 그것은 rowNum만큼 반복한다 라는 뜻이다.
4. DAO클래스에서 JDBCTemplate객체를 얻는 방법
1. JdbcDaoSupport클래스 상속방법
ㄱ) DAO클래스를 구현할 때 JdbcDaoSupport클래스를 부모클래스로 지정한다.
(JdbcDaoSupport클래스를 부모로 지정하면 getJdbcTemplate()메소드를 상속받을 수 있다.)
ㄴ) JdbcTemplate( ) 메소드를 호출
(getJdbcTemplate( )메소드를 호출하면 JdbcTemplate객체가 리턴되어
모든 메소드를 JdbcTemplate 객체로 구현할 수 있다.)
ㄷ) getJdbcTemplate() 메소드가 JdbcTemplate 객체를 리턴하려면 DataSource객체를 가지고 있어야 한다.
따라서, 반드시 부모 클래스인 JdbcDaoSupport클래스의 setDataSource() 메소드를 호출하여 데이터소스
객체를 의존성 주입해야한다.
ㄹ) setDataSource( ) 메소드에 @Autowired 어노테이션을 추가로 붙인다. 이렇게 @Autowired를 선언하면
해당 메소드를 스프링 컨테이너가 자동으로 호출해주며, 이때 메소드 매개변수 타입을 확인하고 해당 타입의 객 체가 메로리에 존재하면 그 객체를 인자로 넘겨준다.
@Repository
public class BoardDAOSpring extends JdbcDaoSupport {
// SQL명령어들
private final String BOARD_INSERT = "insert into board(seq, title, writer, content) values((select nvl(max(seq),0)+1 from board),?,?,?)";
private final String BOARD_UPDATE = "updqte board set title=?, content=? where seq=?";
private final String BOARD_DELETE = "delete board where seq=?";
private final String BOARD_GET = "select * from board where seq=?";
private final String BOARD_LIST = "select * from board order by seq desc ";
public BoardDAOSpring(){
}
@Autowired
public void setSuperDataSource(DataSource dataSource) {
super.setDataSource(dataSource);
}
/** CRUD 기능의 메소드 구현 : create Read update delete**/
// 글등록
public void insertBoard(BoardVO vo) {
System.out.println("===>Spring JDBC로 insertBoard()기능처리");
getJdbcTemplate().update(BOARD_INSERT, vo.getTitle(), vo.getWriter(), vo.getContent());
}
// 글수정
public void updateBoard(BoardVO vo) {
System.out.println("===>Spring JDBC로 updateBoard()기능처리");
getJdbcTemplate().update(BOARD_UPDATE, vo.getTitle(), vo.getContent(), vo.getSeq());
}
// 글 삭제
public void deleteBoard(BoardVO vo) {
System.out.println("===>Spring JDBC로 deleteBoard()기능처리");
getJdbcTemplate().update(BOARD_DELETE, vo.getSeq());
}
// 글 상세 조회
public BoardVO getBoard(BoardVO vo) {
System.out.println("===>Spring JDBC로 insertBoard()기능처리");
Object[] args = { vo.getSeq() };
return getJdbcTemplate().queryForObject(BOARD_GET, args, new BoardRowMapper());
}
// 글 목록 조회
public List<BoardVO> getBoardList(BoardVO vo) {
System.out.println("===>Spring JDBC로 insertBoard()기능처리");
return getJdbcTemplate().query(BOARD_LIST, new BoardRowMapper());
}
-------------------------------------------------------------------------------------------------
/**RowMapper관련 클래스**/
class BoardRowMapper implements RowMapper<BoardVO> {
public BoardVO mapRow(ResultSet rs, int rowNum) throws SQLException {
BoardVO board = new BoardVO();
board.setSeq(rs.getInt("seq"));
board.setTitle(rs.getString("title"));
board.setWriter(rs.getString("writer"));
board.setContent(rs.getString("content"));
board.setRegDate(rs.getDate("regdate"));
board.setCnt(rs.getInt("cnt"));
return board;
}
}
}
2. JdbcTemplate클래스 <bean>등록->의존성 주입
1. applicationContext.xml에 JdbcTemplate 클래스를 <bean>등록한다.
2. DAO클래스에 JdbcTemplate객체에 DataSource객체를 의존성 주입해야한다.
@Autowired
private JdbcTemplate jdbcTemplate;
<!-- XML설정부분-->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
<context:component-scan base-package="com.jbr.biz"></context:component-scan>
<!-- DataSource -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- Spring JDBC : jdbcTemplate의 메서드 사용을 위한 등록 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
</<beans>
----------------------------------------------------------------------------------------------------------
@Repository("boardDAOspring")
public class BoardDAOSpring{
// SQL명령어들
private final String BOARD_INSERT = "insert into board(seq, title, writer, content) values((select nvl(max(seq),0)+1 from board),?,?,?)";
private final String BOARD_UPDATE = "updqte board set title=?, content=? where seq=?";
private final String BOARD_DELETE = "delete board where seq=?";
private final String BOARD_GET = "select * from board where seq=?";
private final String BOARD_LIST = "select * from board order by seq desc ";
@Autowired
private JdbcTemplate jdbcTemplate;
// CRUD 기능의 메소드 구현
// 글등록
public void insertBoard(BoardVO vo) {
System.out.println("BoardDAOSpring로 insertBoard() 기능처리");
jdbcTemplate.update(BOARD_INSERT, vo.getTitle(), vo.getWriter(), vo.getContent());
}// insertBoard() END
// 글수정
public void updateBoard(BoardVO vo) {
System.out.println("BoardDAOSpring로 updateBoard() 기능 처리");
jdbcTemplate.update(BOARD_UPDATE, vo.getTitle(), vo.getContent(), vo.getSeq());
}// updateBoard() END
// 글삭제
public void deleteBoard(BoardVO vo) {
System.out.println("BoardDAOSpring로 deleteBoard()기능 처리");
jdbcTemplate.update(BOARD_DELETE, vo.getSeq());
}// deleteBoard() END
// 글 상세조회
public BoardVO getBoard(BoardVO vo) {
System.out.println("BoardDAOSpring로 getBoard() 기능 처리");
Object[] args = { vo.getSeq() };
return jdbcTemplate.queryForObject(BOARD_GET, args, new BoardRowMapper());
}// getBoard() END
// 글 목록조회
public List<BoardVO> getBoardList(BoardVO vo) {
System.out.println("BoardDAOSpring로 getBoard() 기능 처리");
return jdbcTemplate.query(BOARD_LIST, new BoardRowMapper());
}// getBoardList() END
}
----------------------------------------------------------------------------------------------------------
/**RowMapper관련 클래스**/
public class BoardRowMapper implements RowMapper<BoardVO> {
public BoardRowMapper() {
}
@Override
public BoardVO mapRow(ResultSet rs, int rowNum) throws SQLException {
BoardVO board = new BoardVO();
board.setSeq(rs.getInt("seq"));
board.setTitle(rs.getString("title"));
board.setWriter(rs.getString("writer"));
board.setContent(rs.getString("content"));
board.setRegDate(rs.getDate("regdate"));
board.setCnt(rs.getInt("cnt"));
return board;
}
}
'Framework > Spring' 카테고리의 다른 글
Spring-어노테이션 기반 MVC개발 (0) | 2021.06.23 |
---|---|
Spring-Transaction(트랜잭션) (0) | 2021.06.23 |
Spring-AOP(어노테이션 기반) (0) | 2021.06.22 |
Spring-AOP(XML 기반) (0) | 2021.06.22 |
Spring-AOP(advice) (0) | 2021.06.21 |