[Day 27 | Spring] JDBC Template(2) + 실습 코드

y♡ding·2024년 11월 19일

데브코스 TIL - Spring

목록 보기
16/46

JDBC Template

Spring Framework의 JdbcTemplate은 데이터베이스 작업을 단순화하고 반복적인 코드를 제거하여 SQL 중심의 데이터 액세스를 쉽게 해주는 클래스입니다. JDBC API를 캡슐화하여 사용자가 직접 연결(Connection) 객체를 생성하거나 자원을 정리할 필요가 없습니다.


1. 개념 및 특징

1.1 주요 특징

  1. 반복 제거: 연결, 명령 실행, 결과 처리 등 반복적인 코드를 최소화.
  2. SQL 중심: ORM보다 SQL 작성이 더 직관적이며 자유롭습니다.
  3. 자원 관리: Connection, Statement, ResultSet 등의 자원을 자동으로 관리.
  4. 풀링: Spring Boot는 기본적으로 데이터베이스 연결 풀을 사용(Datasource 관리).

1.2 주요 메서드

  1. queryForObject

    • 단일 행과 단일 열의 값을 조회.
    • 예: 현재 시간을 조회하거나 특정 조건의 단일 값을 반환.
    String result = jdbcTemplate.queryForObject("SELECT NOW() AS NOW", String.class);
  2. queryForList

    • 다중 행을 List<Map<String, Object>> 형식으로 반환.
    • 각 행은 Map 형태로 표현되며, 열 이름이 키(Key)입니다.
    List<Map<String, Object>> results = jdbcTemplate.queryForList("SELECT * FROM dept");
    
  3. query

    • 결과를 사용자 정의 객체로 매핑.
    • BeanPropertyRowMapper를 사용하여 SQL 결과를 자바 객체로 변환.
    List<DeptTO> results = jdbcTemplate.query(
        "SELECT * FROM dept",
        new BeanPropertyRowMapper<>(DeptTO.class)
    );

2. JDBC Template과 의존성 주입

JdbcTemplate 객체는 Spring에서 DataSource를 주입받아 생성됩니다. Spring Boot에서는 기본적으로 HikariCP 풀링을 사용하여 효율적인 데이터베이스 연결을 제공합니다.

// JdbcDAO
@Repository
public class JdbcDAO {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public JdbcDAO() {
        System.out.println("JdbcDAO 생성자 호출");
        System.out.println("JdbcDAO 생성자: " + jdbcTemplate);  // null
    }

    public void selectType() {
        System.out.println("selectType(): " + jdbcTemplate); // org.springframework.jdbc.vore.JdbcTemplate@205ac58c

        String result = jdbcTemplate.queryForObject("select now() as now", String.class);
        System.out.println("현재 시간: " + result);
    }
}

// 메인
@SpringBootApplication
public class Jdbc02Application implements CommandLineRunner {

    @Autowired
    private JdbcDAO dao;

    public static void main(String[] args) {
        SpringApplication.run(Jdbc02Application.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        dao.selectType();
    }
}

실행 흐름

  1. 스프링 컨테이너가 빈 생성:
    • JdbcDAO 객체를 생성하며 생성자를 호출.
    • 생성자 내에서 jdbcTemplate은 아직 초기화되지 않았기 때문에 null 출력.
  2. 의존성 주입:
    • 스프링이 @Autowired 등을 통해 jdbcTemplate을 주입.
  3. 메서드 실행:
    • 이후 호출되는 메서드에서는 의존성 주입이 완료된 jdbcTemplate을 사용할 수 있으므로, 참조값이 출력됨.

3. 실습 및 코드 설명

3.1 현재 시간 조회

JdbcTemplate을 사용하여 데이터베이스에서 현재 시간을 조회하고 출력합니다.

// JdbcDAO
@Repository
public class JdbcDAO {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public JdbcDAO() {
        System.out.println("JdbcDAO 생성자 호출");
        System.out.println("JdbcDAO 생성자: " + jdbcTemplate);  // null
    }

    public void selectType() {
        System.out.println("selectType(): " + jdbcTemplate); // org.springframework.jdbc.vore.JdbcTemplate@205ac58c

        String result = jdbcTemplate.queryForObject("select now() as now", String.class);
        System.out.println("현재 시간: " + result);
    }
}

// 메인
@SpringBootApplication
public class Jdbc02Application implements CommandLineRunner {

    @Autowired
    private JdbcDAO dao;

    public static void main(String[] args) {
        SpringApplication.run(Jdbc02Application.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        dao.selectType();
    }
}

3.2 데이터베이스 목록 출력

queryForList를 사용하여 여러 데이터베이스 이름을 출력합니다.

List<Map<String, Object>> results = jdbcTemplate.queryForList("SHOW DATABASES");
for (Map<String, Object> map : results) {
    System.out.println(map.get("Database")); // 각 데이터베이스 이름 출력
}

3.3 DeptDAO로 데이터베이스 작업

(1) DeptTO를 사용하지 않고 Map으로 처리
// DeptDAO 
@Repository
public class DeptDAO {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public void listDept() {
        List<Map<String, Object>> results = jdbcTemplate.queryForList("select * from dept");
        for (Map<String, Object> result : results) {
            System.out.println(result.get("deptno" + "/" + result.get("dname") + "/" + result.get("loc")));
        }
    }
}

// 실행
@SpringBootApplication
public class Jdbc02Application implements CommandLineRunner {

    @Autowired
    private DeptDAO dao;

    public static void main(String[] args) {
        SpringApplication.run(Jdbc02Application.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        dao.listDept();
    }
}
(2) DeptTO를 사용하여 객체로 변환
  • BeanPropertyRowMapper를 활용하여 결과를 객체로 매핑.
// DeptTO
@Setter
@ToString
public class DeptTO {
    private String deptno;
    private String dname;
    private String loc;

}

// DeptDAO
@Repository
public class DeptDAO {

    **@Autowired
    private JdbcTemplate jdbcTemplate;

    public void listDept() {
        ArrayList<DeptTO> results = (ArrayList<DeptTO>) jdbcTemplate
                .query("select * from dept",
                        new BeanPropertyRowMapper<>(DeptTO.class));**
        for (DeptTO to : results) {
            System.out.println(to);
        }
    }
}

(3) 조건 추가 및 리펙토링
  • 쿼리에 매개변수를 전달하여 조건부 검색 구현.
public void listDept(String deptno) {
    String sql = "SELECT * FROM dept WHERE deptno = ?";
    List<DeptTO> results = jdbcTemplate.query(
        sql,
        new BeanPropertyRowMapper<>(DeptTO.class),
        deptno
    );

    for (DeptTO to : results) {
        System.out.println(to);
    }
}

3.4 우편번호 검색기

(1) 데이터 전송 객체
@Getter
@Setter
public class ZipcodeTO {
    private String zipcode;
    private String sido;
    private String gugun;
    private String dong;
    private String ri;
    private String bunji;
}
(2) DAO 구현
  • 입력한 동 이름으로 우편번호를 검색합니다.
@Repository
public class ZipcodeDAO {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public List<ZipcodeTO> searchZipcode(String strDong) {
        String sql = "SELECT zipcode, sido, gugun, dong, ri, bunji FROM zipcode WHERE dong LIKE ?";
        return jdbcTemplate.query(
            sql,
            new BeanPropertyRowMapper<>(ZipcodeTO.class),
            strDong + "%"
        );
    }
}
(3) 실행 클래스
  • 실행 시 검색어를 입력받아 검색 결과를 출력합니다.
@SpringBootApplication
public class Zipcode01Application implements CommandLineRunner {

    @Autowired
    private ZipcodeDAO dao;

    public static void main(String[] args) {
        SpringApplication.run(Zipcode01Application.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        List<ZipcodeTO> lists = dao.searchZipcode(args[0]);
        for (ZipcodeTO to : lists) {
            System.out.printf("[%s] %s %s %s %s %s %n",
                to.getZipcode(), to.getSido(), to.getGugun(), to.getDong(), to.getRi(), to.getBunji());
        }
    }
}

4. 정리

  1. JdbcTemplate 개념
    • SQL 중심의 데이터 접근을 간소화하고, 자원 관리 및 반복 작업을 제거.
  2. 주요 메서드
    • queryForObject, queryForList, query를 사용하여 단일 값, 다중 값, 객체로 결과 처리 가능.
  3. Spring과의 통합
    • JdbcTemplate은 Spring이 관리하는 데이터 소스를 통해 동작하며, @Autowired로 의존성 주입됨.
  4. 실습 활용
    • Map과 객체 변환(BeanPropertyRowMapper)을 통해 데이터를 유연하게 처리 가능.
  5. 활용 예시
    • 조건부 검색, 목록 출력, 실시간 데이터 처리 등에 유용하게 사용.

0개의 댓글