본문 바로가기
Java

[SpringBoot] RestApi 만들기 (5.3) jdbcTemplate - Select

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

SpringBoot
jdbcTemplate
NamedParameterJdbcTemplate

 

지난 시리즈에 이어서, 

Select 로 리스트 조회까지 했습니다.

이번엔 Select 문에 조건절을 던져서 조회하는걸 해보겠습니다.

이런 쿼리,
SELECT * FROM world.city WHERE CountryCode = 'KOR' AND Population > 2000000;

 

아, 그전에

지금까지 @GetMapping 만 사용했는데 @RequestMapping 을 class 에 붙히도록 소스를 변경했습니다.
여기 참고해주세요.

InfoController.java

더보기
package com.bryan.hello.preword.info;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.bryan.hello.preword.info.model.City;
import com.bryan.hello.preword.info.model.Project;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequestMapping("info")
public class InfoController {

	private InfoService infoService;
	
	@Autowired
	public InfoController(InfoService infoService) {
		this.infoService = infoService;
	}
	
	
	@GetMapping("project")
	public Object projectInfo() {
		log.debug("/info start");
		Project project = infoService.getProjectInfo();
		return project;
	}


	@GetMapping("custom")
	public String customJson() {
		JsonObject jo = new JsonObject();
		
		jo.addProperty("projectName", "preword");
		jo.addProperty("author", "hello-bryan");
		jo.addProperty("createdDate", new Date().toString());
		
		JsonArray ja = new JsonArray();
		for(int i=0; i<5; i++) {
			JsonObject jObj = new JsonObject();
			jObj.addProperty("prop"+i, i);
			ja.add(jObj);
		}
		
		jo.add("follower", ja);
		
		return jo.toString();
	}
	
	@GetMapping("cityList")
	public Object cityList() {
		log.debug("/cityList start");
		List<City> cityList = infoService.getCityList();
		return cityList;
	}
	
}

 

조회하는 값은 url parameter 로 받아오는것 부터 하겠습니다. 

두가지 방법이 있습니다.

  • localhost:8000/info/project/KOR/3000000
  • localhost:8000/info/project?countryCode=KOR&population=3000000

1. @PathVariable

@GetMapping("cityListByCode/{countryCode}/{population}")
public Object cityByCountryCode(@PathVariable("countryCode") String ctCode, @PathVariable("population") int population) {
	log.debug("countryCode = {}, population {}", ctCode, population);
	List<City> cityList = infoService.findCityByCodeAndPopulation(ctCode, population);
	return cityList;
}

localhost:8000/info/cityListByCode/KOR/3000000

위와같이 호출하면 ctCode="KOR", population=3000000 이 넘어오게 됩니다.

그 값으로 service 의 method 를 호출하면 됩니다.

 

2. @RequestParam

@GetMapping("cityListByCode")
public Object cityByCountryCode(@RequestParam("countryCode") String ctCode
		, @RequestParam(value="population", required = false, defaultValue = "0") int population) {
	log.debug("countryCode = {}, population = {}", ctCode, population);
	List<City> cityList = infoService.findCityByCodeAndPopulation(ctCode, population);
	return cityList;
}

이렇게 파라메터를 받도록 하고, 
http://localhost:8000/info/cityListByCode?countryCode=KOR
get 방식의 parameter 로 넘기면, 

로그는 countryCode = KOR, population = 0 이렇게 나옵니다.

population 이 기본값으로 0 을 설정했기 때문입니다. 직접 파라메터로 넘기려면

http://localhost:8000/info/cityListByCode?countryCode=KOR&population=1000000

이렇게 호출하면 됩니다.

두가지 방법을 혼용해서 사용할 수 있습니다.

 

이렇게 client 단에서 파라메터를 넘겨 준다고 가정하고, 

다시 Service 코드를 보면,

public List<City> findCityByCodeAndPopulation(String countryCode, int population) {
	log.debug("countryCode = {}, population = {}", countryCode, population);
	return this.cityRepository.findByCountryCodeAndPopulation(countryCode, population);
}

여기서 repository 에 method 를 추가하겠습니다.

 

SQL 을 좀 수정해서 반복되는 부분을 따로 빼도록 하겠습니다.

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

class CitySql {
	public static final String SELECT = """
		SELECT ID, Name, CountryCode, District, Population FROM city WHERE 1=1 
	""";
	
	public static final String COUNTRY_CODE_CONDITION = """
		AND countryCode = :countryCode
	""";
	
	public static final String POPULATION_CONDITION = """
		AND population >= :population
	""";
}

이렇게 만들고, 쿼리는 SELECT + COUNTRY_CODE_CONDITION + POPULATION_CONDITION 이렇게 만들겁니다.

그리고 statement 파라메터가 :columnName 으로 되어있는데 여기로 파라메터를 전달합니다.

Repository 에 다음 함수를 추가합니다.

public List<City> findByCountryCodeAndPopulation(String countryCode, int population){
		
	String qry = CitySql.SELECT
			+ CitySql.COUNTRY_CODE_CONDITION
			+ CitySql.POPULATION_CONDITION;

	SqlParameterSource param = new MapSqlParameterSource("countryCode", countryCode)
			.addValue("population", population);
	
	return namedParameterJdbcTemplate.query(qry, param, this.cityRowMapper);
}

qry 를 만들고 :columnName 으로 조회합니다. 파라메터를 전달하기 위해서 MapSqlParameterSource 를 통해서 

값을 전달합니다.

그리고 return 에

namedParameterJdbcTemplate 으로 쿼리를 날립니다.

파라메터는 param 을 통해서 전달.
CityMapper 는 리턴된 값을 class 와 mapping 해서 리턴.

서비스에서 메소드 추가

public List<City> findCityByCodeAndPopulation(String countryCode, int population) {
	log.debug("countryCode = {}, population = {}", countryCode, population);
	return this.cityRepository.findByCountryCodeAndPopulation(countryCode, population);
}

이 서비스를 Controller 에서 호출하도록 추가

InfoController.java (@PathVariable)

@GetMapping("cityListByCode/{countryCode}/{population}")
public Object cityByCountryCode(@PathVariable("countryCode") String ctCode, @PathVariable("population") int population) {
	log.debug("countryCode = {}, population = {}", ctCode, population);
	List<City> cityList = infoService.findCityByCodeAndPopulation(ctCode, population);
	return cityList;
}

또는 @RequestParam 으로 받으려면

@GetMapping("cityListByCode")
public Object cityByCountryCode(@RequestParam("countryCode") String ctCode
		, @RequestParam(value="population", required = false, defaultValue = "0") int population) {
	log.debug("countryCode = {}, population = {}", ctCode, population);
	List<City> cityList = infoService.findCityByCodeAndPopulation(ctCode, population);
	return cityList;
}

 

 

결과

 

 

Spring Boot Tutorial 시리즈

Spring Boot Tutorial 부록

728x90
반응형

댓글