Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Archives
Today
Total
관리 메뉴

Everything has an expiration date

[inflearn] 20240121 [스프링-프레임워크] - 24강 필기 본문

[Inflearn]/자바 스프링 프레임워크(renew ver.)

[inflearn] 20240121 [스프링-프레임워크] - 24강 필기

Jelly-fish 2024. 1. 21. 23:04

24강 - JdbcTemplate

Java 언어를 사용해서 Database 와 통신하기 위한 방법에 대해서 살펴본다.

24-1 JDBC의 단점을 보완한 JdbcTemplate
24-2 DataSource 클래스

 

24-1 JDBC의 단점을 보완한 JdbcTemplate

 

【 JDBC 】

 

① 드라이버 로딩
② DB 연결
③ SQL 작성 및 전송
④ 자원 해제

【 JdbcTemplate 】

 

① JdbcTemplate
    ▶ (드라이버 로딩, DB 연결, 자원해제)
② SQL 작성 및 전송

 

→ Spring 에서는 동일한 작업 (드라이버 로딩, DB 연결, 자원해제)이 반복되는 것을 막기 위해

    Jdbc Template 을 제공하고 있다.


 

24-2 DataSource 클래스

 

◎ DriverManagerDataSource

  • 데이터베이스 연결과 관련된 정보(데이터베이스 경로, Url, 유저 ID, PW) 를 갖고 있는 객체.
  • `DataSource` 는 Spring 또는 c3p0에 제공하는 클래스를 이용할 수 있다.

 

Spring

▶ `org.springframework.jdbc.datasource.DriverManagerDataSource`

 

c3p0

▶ `com.mchange.v2.c3p0.DriverManagerDataSource`


JdbcTemplate 사용을 위한 과정

 

1. pom.xml 수정 - 의존 설정

pom.xml
<repositories>
    <repository>
        <id>oracle</id>
        <name>ORACLE JDBC Repository</name>
        <url>http://maven.jahia.org/maven2</url>
    </repository>
</repositories>


<!-- Spring JDBC 등록 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>4.1.6.RELEASE</version>
</dependency>

<!-- c3p0 모듈 등록 -->
<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5</version>
</dependency>

 

→ `oracle repository`를 추가했기 때문에 Spring JDBC, c3p0 의존 설정이 가능한 것이다.

 

 

2-1. DAO 클래스 수정

① `c3p0`의 `DriverManagerdataSource`를 사용했을 경우.

 

① MemberDao.java
package com.bs.lec23.member.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.bs.lec23.member.Member;
import com.mchange.v2.c3p0.DriverManagerDataSource;	//-- ①

@Repository
public class MemberDao implements IMemberDao
{
    private String driver = "oracle.jdbc.driver.OracleDriver";
    private String url = "jdbc:oracle:thin:@localhost:1521:xe";
    private String userid = "scott";
    private String userpw = "tiger";
    
    // ① c3p0 의 DriverManagerDataSource 를 사용.
    private DriverManagerDataSource dataSource;
    
    private JdbcTemplate template;
    
    /*
    private Connection conn = null;
    prvate PreparedStatement pstmt = null;
    private ResultSet rs = null;
    */
    
    public MemberDao()
    {
        // dataSource 를 이용해서
        // Dao 객체가 생성될 때 딱 한 번만 설정을 하고 넘어갈 수 있도록 한다.
    	dataSource = new DriverManagerDataSource();
        dataSource.setDriverClass(driver);
        dataSource.setJdbcUrl(url);
        dataSource.setUser(userid);
        dataSource.setPassword(userpw);
    }
    
    ....
}

 


② `SpringJDBC`의 `DriverManagerdataSource`를 사용했을 경우.

 

② MemberDao.java
package com.bs.lec23.member.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.bs.lec23.member.Member;

@Repository
public class MemberDao implements IMemberDao
{
    private String driver = "oracle.jdbc.driver.OracleDriver";
    private String url = "jdbc:oracle:thin:@localhost:1521:xe";
    private String userid = "scott";
    private String userpw = "tiger";
    
    //-- ②
    org.springframework.jdbc.datasource.DriverManagerDataSource dataSource;
    
    private JdbcTemplate template;
    
    public MemberDao()
    {
        // dataSource 를 이용해서
        // Dao 객체가 생성될 때 딱 한 번만 설정을 하고 넘어갈 수 있도록 한다.
        dataSource = new org.springframework.jdbc.datasource.DriverManagerdataSource();
        dataSource.setDeiverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUserName(userid);
        dataSource.setPassword(userpw);
    }
    
    ....
}

 


DriverManagerDataSource - 메소드명 차이점 표 정리

 

→ DriverManagerDataSource 를 어떤 클래스(`c3p0`, `SpringJDBC`)에서 사용했느냐에 따라

    메소드명에 차이가 존재한다.

 

구분 c3p0 Spring JDBC
드라이버 로딩 setDriverClass(driver) setDriverClassName(driver);
DB 연결 setJdbcUrl(url) setUrl(url)
유저 ID setUser(userid) setUserName(userid)
유저 PW setPassword(userpw) setPassword(userpw)

 


 

2-2. DAO 클래스 수정 - `c3p0` DriverManagerDataSource 사용.

MemberDao.java
package com.bs.lec23.member.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.bs.lec23.member.Member;
import com.mchange.v2.c3p0.DriverManagerDataSource;	//-- ①

@Repository
public class MemberDao implements IMemberDao
{
    private String driver = "oracle.jdbc.driver.OracleDriver";
    private String url = "jdbc:oracle:thin:@localhost:1521:xe";
    private String userid = "scott";
    private String userpw = "tiger";
    
    // ① c3p0 의 DriverManagerDataSource 를 사용.
    private DriverManagerDataSource dataSource;
    
    private JdbcTemplate template;
    
    public MemberDao()
    {
        // dataSource 를 이용해서
        // Dao 객체가 생성될 때 딱 한 번만 설정을 하고 넘어갈 수 있도록 한다.
    	dataSource = new DriverManagerDataSource();
        dataSource.setDriverClass(driver);
        dataSource.setJdbcUrl(url);
        dataSource.setUser(userid);
        dataSource.setPassword(userpw);
        
        template = new JdbcTemplate();
        template.setDatasource(dataSource);
    }
    

}

 


Ⅲ. JDBC Template 적용 완료!

 

데이터베이스와 관련된 정보`dataSource` 라는 객체에 모두 set 하여 담아준다.
dataSource = new DriverManagerDataSource();
dataSource.setDriverClass(driver);
dataSource.setJdbcUrl(url);
dataSource.setUser(userid);
dataSource.setPassword(userpw);​


이후, 그것을 더 이상 반복해서 작업하지 않도록 `JdbcTemplate`에 다시 set 을 해 주는 것이다.
template = new JdbcTemplate();
template.setDatasource(dataSource);​


이렇게 처리하게 되면, 더 이상 우리는 DAO 의 메소드를 정의할 때마다
① 드라이버 로딩, ② DB 연결, ④ 자원 해제 의 과정을 반복하지 않아도 된다!

Ⅳ. JdbcTemplate 를 적용한 후, MemberDAO 의 메소드 수정하기

① `int memberInsert(Member member)` 메소드 수정.
@Override
public int memberInsert(Member member)
{
    int result = 0;
    
    String sql = "INSERT INTO MEMBER (MEMID, MEMPW, MEMMAIL)"
               + " VALUES (?, ?, ?)";

    result = template.update(sql, member.getMemId(), member.getMemPw(), member.getMemMail());

    return result;
}

코드가 굉장히 간결해 진 것을 확인할 수 있다! 


★ [Check!!!]

 

result = template.update(sql, member.getMemId(), member.getMemPw(), member.getMemMail());
                        ===== ===========================================================
                          ①                                ②           
                       [쿼리문]   [PrepareStatement 로 set 해 주어야하는 ? 에 들어가야 할 값.]

 

▶ `PrepareStatement` 로 `pstmt.setXxx(index, value)` 해야 하는 부분을 `template.update(sql, v1, v2, v3)` 로 처리했다.


★ ② `Member memberSelect(Member member)` 메소드 수정.
@Override
public Member memberSelect(Member member)
{
    List<Member> members = null;
    
    String sql = "SELECT *"
              + " FROM MEMBER"
              + " WHERE MEMID=?"
              +   " AND MEMPW=?";
    
    members = template.query(sql, new PreparedStatementSetter() {
    	
        @Override
        public void setValues(PreparedStatement pstmt) throws SQLException
        {
            pstmt.setString(member.getMemId());
            pstmt.setString(member.getMemPw());
        }
    
    }, new RowMapper<Member>() {
    
        @Override
        public Member mapRow(ResultSet rs, int rowNum) throws SQLException
        {
            Member mem = new Member();
            mem.setMemId(rs.getString("MEMID"));
            mem.setMemPw(rs.getString("MEMPW"));
            mem.setMemMail(rs.getString("MEMMAIL"));
            mem.setMemPurcNum(rs.getInt("MEMPURCNUM"));
            
            return mem;
        }
    
    });
    
    if (members.isEmpty())
    	return null;
	
    return members.get(0);

}

 

[Check!!!]  

 

▶ 『`PreparedStatementSetter()`』

  • String으로 표현된 쿼리문의 ? 로 표현된 부분을 set 해 주기 위한 객체이다.

▶ 『`RowMapper()`』

  • Database 에서 Select 를 통해 얻어온 회원 정보를 맵핑 해준다.

 

① 익명 클래스에서 사용할 때 값이 변경될 수 있으므로 `final String sql` 로 선언해도 된다.
final String sql = "SELECT *"
                + " FROM MEMBER"
                + " WHERE MEMID=?"
                +   " AND MEMPW=?";

 


★② 두 번째 매개변수로 『`PreparedStatementSetter()`』 객체와 『익명 클래스』 를 선언해 준다.

 

members = template.query(sql, new PreparedStatementSetter() {

    @Override
    public void setValues(PreparedStatement pstmt) throws SQLException
    {
        pstmt.setString(member.getMemId());
        pstmt.setString(member.getMemPw());
    }

}, arg2);

 

▶ 익명 클래스 내부에서, `PreparedStatementSetter()` 의 메소드인

     `void setValues(PreparedStatement pstmt)`를 `@Override` 해 준 후, 필요한 값을 채워준다.

 


 

★③ 세 번째 매개변수로 『`RowMapper<Member>()`』 객체와 『익명 클래스』 를 선언해 준다.

 

members = template.query(sql, new PreparedStatementSetter() {

    @Override
    public void setValues(PreparedStatement pstmt) throws SQLException
    {
        pstmt.setString(member.getMemId());
        pstmt.setString(member.getMemPw());
    }

}, new RowMapper<Member>() {

    @Override
    public Member mapRow(ResultSet rs, int rowNum) throws SQLException
    {
        Member mem = new Member();
        mem.setMemId(rs.getString("MEMID"));
        mem.setMemPw(rs.getString("MEMPW"));
        mem.setMemMail(rs.getString("MEMMAIL"));
        mem.setMemPurcNum(rs.getInt("MEMPURCNUM"));

        return mem;
    }

});

 

▶ 익명 클래스 내부에서, ` RowMapper()` 의 메소드인

    `Object mapRow(ResultSet rs, int rowNum)`를 `@Override` 해 준 후,

     `ResultSet` 에서 가져온 값들을 `member` 객체에 하나씩 set 하여 담아준다.


실행 결과 스크린샷
  • 실행 결과는 이전과 동일하다. JdbcTemplate를 통해  코드 작성 단계에서의 반복을 없애준 것 뿐이다.

출처 : inflearn [스프링-프레임워크(renew)] - 24강