능글맞은 구렁이

Spring-JDBC(Oracle) 본문

Framework/Spring

Spring-JDBC(Oracle)

보라색츄르 2021. 6. 22. 23:01

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
Comments