기존
@RestController
public class FruitController {
private final JdbcTemplate jdbcTemplate;
public FruitController(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@PostMapping("/api/v1/fruit")
public void saveFruit(@RequestBody FruitRequestDTO request){
String sql = "INSERT INTO fruit (name, warehousingDate, price) VALUES (?, ?, ?)";
jdbcTemplate.update(sql, request.getName(), request.getWarehousingDate(), request.getPrice());
}
@PutMapping("/api/v1/fruit")
public void updateFruit(@RequestBody FruitRequestDTO request) {
String readSql = "SELECT * FROM fruit WHERE id = ?";
boolean isFruitNotExist = jdbcTemplate.query(readSql, (rs, rowNum) -> 0, request.getId()).isEmpty();
if(isFruitNotExist) {
throw new IllegalArgumentException();
}
String sql = "UPDATE fruit SET soleOutYN = 'Y' WHERE id = ?";
jdbcTemplate.update(sql, request.getId());
}
@GetMapping("/api/v1/fruit/stat")
public FruitResponseDTO salesStat(@RequestParam String name){
String readSql = "SELECT * FROM fruit WHERE name = ?";
boolean isFruitNotExist = jdbcTemplate.query(readSql, (rs, rowNum) -> 0, name).isEmpty();
if(isFruitNotExist) {
throw new IllegalArgumentException();
}
String salesAmountSql = "SELECT SUM(price) FROM fruit WHERE name = ? AND soleOutYN = 'Y'";
String notSalesAmountSql = "SELECT SUM(price) FROM fruit WHERE name = ? AND soleOutYN = 'N'";
long salesAmount = jdbcTemplate.queryForObject(salesAmountSql, long.class, name);
long notSalesAmount = jdbcTemplate.queryForObject(notSalesAmountSql, long.class, name);
return new FruitResponseDTO(salesAmount, notSalesAmount);
}
}
비즈니스 로직, db 연결이 다 같이 있음...
Controller
@RestController
@RequestMapping("/api/v1/fruit")
public class FruitController {
private final FruitService fruitService;
public FruitController(FruitService fruitService) {
this.fruitService = fruitService;
}
@PostMapping
public void saveFruit(@RequestBody FruitRequestDTO request){
fruitService.saveFruit(request);
}
@PutMapping
public void updateFruit(@RequestBody FruitRequestDTO request) {
fruitService.updateFruit(request);
}
@GetMapping("/stat")
public FruitResponseDTO salesStat(@RequestParam("name") String name){
return fruitService.salesStat(name);
}
}
Service
@Service
public class FruitService {
private final FruitRepository fruitRepository;
public FruitService(FruitRepository fruitRepository) {
this.fruitRepository = fruitRepository;
}
public void saveFruit(FruitRequestDTO request){
fruitRepository.saveFruit(request.getName(), request.getWarehousingDate(), request.getPrice());
}
public void updateFruit(FruitRequestDTO request){
boolean isFruitNotExist = fruitRepository.findById(request.getId());
if(isFruitNotExist) {throw new IllegalArgumentException("과일이 존재하지 않습니다.");}
fruitRepository.updateFruit(request.getId());
}
public FruitResponseDTO salesStat(String name){
boolean isFruitNotExist = fruitRepository.findByName(name);
if(isFruitNotExist) {throw new IllegalArgumentException("과일이 존재하지 않습니다.");}
long salesAmount = fruitRepository.salesAmount(name);
long notSalesAmount = fruitRepository.noSalesAmount(name);
return new FruitResponseDTO(salesAmount, notSalesAmount);
}
}
Repository
@Repository
public class FruitRepository {
private final JdbcTemplate jdbcTemplate;
public FruitRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void saveFruit(String name, LocalDate warehousingDate, long price){
String sql = "INSERT INTO fruits (name, warehousingDate, price) VALUES (?, ?, ?)";
jdbcTemplate.update(sql, name, warehousingDate, price);
}
public boolean findById(long id){
String readSql = "SELECT * FROM fruits WHERE id = ?";
return jdbcTemplate.query(readSql, (rs, rowNum) -> 0, id).isEmpty();
}
public void updateFruit(long id) {
String sql = "UPDATE fruits SET soldYN = 'Y' WHERE id = ?";
jdbcTemplate.update(sql, id);
}
public boolean findByName(String name){
String readSql = "SELECT * FROM fruits WHERE name = ?";
return jdbcTemplate.query(readSql, (rs, rowNum) -> 0, name).isEmpty();
}
public long salesAmount(String name) {
String salesAmountSql = "SELECT SUM(price) FROM fruits WHERE name = ? AND soldYN = 'Y'";
return jdbcTemplate.queryForObject(salesAmountSql, long.class, name);
}
public long noSalesAmount(String name) {
String notSalesAmountSql = "SELECT SUM(price) FROM fruits WHERE name = ? AND soldYN = 'N'";
return jdbcTemplate.queryForObject(notSalesAmountSql, long.class, name);
}
}
public interface FruitRepository {
public void saveFruit(String name, LocalDate warehousingDate, long price);
public boolean findById(long id);
public void updateFruit(long id);
public boolean findByName(String name);
public long salesAmount(String name);
public long noSalesAmount(String name);
}
FruitMemoryRepository와 FruitMySqlRepository가 FruitRepository 인터페이스를 구현하도록 만들고
서버를 실행하면?

Service에서 어떤 FruitRepository 가져와야할지 몰라 에러가 난다.
FruitMySqlRepository 위에 @Primary를 붙여주면?

로그를 찍어보면 FruitMySqlRepository가 들어와 있는걸 확인할 수 있다.
@Primary는 여러개의 인스턴스 중 하나를 결정해서 빈으로 등록한다.
@Qualifier는 빈에 이름을 줘서 특정 빈을 가져올 때 사용한다.
@Qualifier("mainRepo")
@Repository
public class FruitMemoryRepository implements FruitRepository {...}
FruitMemoryRepository에 @Qualifier를 사용해서 'mainRepo' 라는 이름을 부여한다.
public FruitService(@Qualifier("mainRepo") FruitRepository fruitRepository) {
log.error(fruitRepository.toString());
this.fruitRepository = fruitRepository;
}
FruitRepository 의존성을 주입할 때 @Qualifier를 사용해서 'mainRepo' 이름을 가진 빈을 가져온다.

로그를 찍어보면 FruitMemoryRepository가 들어오는걸 있는걸 확인할 수 있다.
@Primary
@Repository
public class FruitMySqlRepository implements FruitRepository {}
vs
@Qualifier("mainRepo")
@Repository
public class FruitMemoryRepository implements FruitRepository {}

@Qualifier가 이김