본문 바로가기
Java

[SpringBoot] RestApi 만들기 (5.1) MySQL + JDBC Template

by bryan.oh 2021. 7. 4.
반응형

Spring JDBC 사용
namedParameterJdbcTemplate

MySQL 연동하기

처음엔 Mybatis 를 사용하려고 했는데, jdbcTemplate 을 사용하려고 합니다.

이유는 여기 참고 하시고요~

 

이전에 추가했던 mybatis dependency를 빼야겠네요.

implementation 'org.springframework.boot:spring-boot-starter-jdbc' 추가

gradle refresh

 

1. DataBase 준비

테스트할 db가 없다면 

https://dev.mysql.com/doc/index-other.html

위 사이트에서 Example Databases 중에 하나를 다운로드 받습니다.

다운로드 후 압축을 풀면 world.sql 파일이 있습니다.

스크립트 파일을 열어보면 world 라는 이름으로 database 를 생성하고 데이터를 입력하는 쿼리가 있습니다.

Workbench 등 mysql 쿼리를 실행할 수 있는 환경에서 실행합니다.

스키마가 생성되었네요.

db 접속 정보는 src/main/resources/application.yml 에 설정합니다.

 

2. model 생성

city table 이 컬럼수가 적고 테스트 하기 좋을거 같으니 city 테이블의 모델을 생성합니다.

경로는 com.bryan.hello.preword.info.model

City.java

package com.bryan.hello.preword.info.model;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class City {
	private Integer id;
	private String name;
	private String countryCode;
	private String district;
	private Integer population;
}

 

3. Repository 생성

경로는 com.bryan.hello.preword.info.repository

CityRepository.java

package com.bryan.hello.preword.info.repository;

import java.util.List;

import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

import com.bryan.hello.preword.info.model.City;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Repository
public class CityRepository {
	private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
	
	public CityRepository(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
		this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
	}

	public List<City> findList(){
		String sql = "select * from city limit 1000";
		
		log.debug("query : {}", sql);
		
		RowMapper<City> cityMapper = (rs, rowNum) -> {
			City city = new City();
			city.setId(rs.getInt("ID"));
			city.setName(rs.getString("Name"));
			city.setCountryCode(rs.getString("contrycode"));
			city.setDistrict(rs.getString("district"));
			city.setPopulation(rs.getInt("population"));
			return city;
		};
		
		return namedParameterJdbcTemplate.query(sql, new MapSqlParameterSource(), cityMapper);
	}
}

여기서 미리 코드 정리 좀 해야겠습니다.

쿼리 부분

지금 쿼리는 너무 간단하지만, 좀 더 길어지고, 소스에서 비슷한 쿼리를 여기저기에서 사용할수도 있습니다.

그럼 관리하기가 힘들어지겠죠.

class 를 만들어서 Groovy 의 Multiline String 으로 선언합니다.

Goorvy 를 사용하기 위해서 build.gradlepluginsdependencies 에 추가를 합니다.

plugins {
  id 'org.springframework.boot' version '2.5.2'
  id 'io.spring.dependency-management' version '1.0.11.RELEASE'
  id 'java'
  id 'groovy'  // 여기 추가
}

dependencies {
  implementation('org.codehaus.groovy:groovy')  // groovy 추가
}

 

이클립스에서 groovy script 를 작성하기 위해서 plugin 을 설치합니다.

설치 중에 logback m2e 때문에 확인 창이 나오는데, logback m2e 는 uninstall 되고 groovy m2e 가 설치되도록 update 에 체크하시면 됩니다. 이클립스 재시작 후 logback 은 다시 설치하겠냐고 물어보는데, 그때 다시 설치하면 됩니다.

 

4. SQL 관리 - Groovy 파일 생성

같은 repository package 아래에 sql 관련 groovy file 을 생성합니다.

CitySql.groovy

package com.bryan.hello.preword.info.repository;

class CitySql{
	public static final String SELECT = """
		SELECT ID, Name, CountryCode, District, Population FROM city LIMIT 1000;
	""";
}

 

5. RowMapper 생성

그리고 RowMapper 도 공통적으로 사용할것 이므로 MapperClass 로 생성합니다.

		RowMapper<City> cityMapper = (rs, rowNum) -> {
			City city = new City();
			city.setId(rs.getInt("ID"));
			city.setName(rs.getString("Name"));
			city.setCountryCode(rs.getString("contrycode"));
			city.setDistrict(rs.getString("district"));
			city.setPopulation(rs.getInt("population"));
			return city;
		};

CityRepository.java 에 있던 이 부분,

경로는 위와 같은 Repository package 안에

파일명은 CityRowMapper.java

package com.bryan.hello.preword.info.repository;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;
import com.bryan.hello.preword.info.model.City;

public class CityRowMapper implements RowMapper<City> {

	@Override
	public City mapRow(ResultSet rs, int rowNum) throws SQLException {
		City city = new City();
		city.setId(rs.getInt("ID"));
		city.setName(rs.getString("Name"));
		city.setCountryCode(rs.getString("countrycode"));
		city.setDistrict(rs.getString("district"));
		city.setPopulation(rs.getInt("population"));
		return city;
	}

}

CityRepository.java  는 아래와 같이 바뀌겠네요.

package com.bryan.hello.preword.info.repository;

import java.util.List;

import org.springframework.jdbc.core.namedparam.EmptySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

import com.bryan.hello.preword.info.model.City;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Repository
public class CityRepository {
	private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
	private final CityRowMapper cityRowMapper;
	
	public CityRepository(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
		this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
		this.cityRowMapper = new CityRowMapper();
	}

	public List<City> findList(){
		
		log.debug("findList query = {}", CitySql.SELECT);

		return namedParameterJdbcTemplate.query(CitySql.SELECT
				, EmptySqlParameterSource.INSTANCE
				, this.cityRowMapper);
	}
}
  • 쿼리에 파라메터를 넘길 필요가 없으므로 EmptySqlParameterSource.INSTANCE 를 던집니다.
  • 조회된 데이터의 한줄한줄을 cityRowMapper 를 통해 맵핑해 줍니다.

 

6. Service 에서 Repository 사용

이제 Service 에서 Repository 를 이용해 데이터를 조회해 보겠습니다.

InfoService.java  에서 repository 객체 선언하고, 생성자 주입을 한 다음에 getCityList() 를 사용하여 호출.

package com.bryan.hello.preword.info;

import java.util.Date;
import java.util.List;

import org.springframework.stereotype.Service;
import com.bryan.hello.preword.info.model.Project;
import com.bryan.hello.preword.info.model.City;
import com.bryan.hello.preword.info.repository.CityRepository;

@Service
public class InfoService {
	
	private final CityRepository cityRepository;
	
	// spring 4.2 이상은 @Autowired 생략 가능
	public InfoService(CityRepository cityRepository) {
		this.cityRepository = cityRepository;
	}
	
	public Project getProjectInfo() {
		
		Project project = new Project();
		project.projectName = "preword";
		project.author = "hello-bryan";
		project.createdDate = new Date();
		
		return project;
	}
	
	public List<City> getCityList() {
		return this.cityRepository.findList();
	}
}

 

마지막으로 Controller 에 service 호출 하는 부분을 추가합니다.

InfoController.java

	@GetMapping("/cityList")
	public Object cityList() {
		log.debug("/cityList start");
		List<City> cityList = infoService.getCityList();
		return cityList;
	}

 

실행

Spring Boot 서버 실행.

브라우저에서 localhost:8000/cityList 입력

 

Select 성공.

 

현재까지 파일 구조

 

 

다음에는 insert / update / delete 등을 만들어보겠습니다.

To Be Continue..

 

Spring Boot Tutorial 시리즈

Spring Boot Tutorial 부록

 

728x90
반응형

댓글