블로그

[인프런워밍업클럽][BE] 과제4 | 과일가게 API 만들기

문제 1.1.1 DB 테이블 생성HTTP 요청 body에 price가 long이기에 int 말고 bigint로 해 봄primary key가 필요하여 수업에서 썼던 id 컬럼을 생성함.1.2 StoreControllerpackage com.group.libraryapp.controller.store; import com.group.libraryapp.dto.store.request.FruitInsertRequest; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class StoreController { //0. JdbcTemplate 사용하도록 연결 private final JdbcTemplate jdbcTemplate; public StoreController(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } //1. 과일 정보 저장 @PostMapping("/api/v1/fruit") public void insertFruit(@RequestBody FruitInsertRequest request){ String sql = "INSERT INTO fruit(name, warehousingDate, price) values(?,?,?)"; jdbcTemplate.update(sql, request.getName(), request.getWarehousingDate(), request.getPrice()); } } 1.3 FruitInsertRequesthtml body에서 전송된 값을 java 변수 형식으로 변환해서 담아둘 dto가 필요하여 생성함정의된 형식에 맞춰서 생성.package com.group.libraryapp.dto.store.request; import java.util.Date; public class FruitInsertRequest { public String name; public Date warehousingDate; public Long price; public String getName() { return name; } public Date getWarehousingDate() { return warehousingDate; } public Long getPrice() { return price; } } 1.4 시연 결과postman 결과mysql 결과중간에 Date 값이 제대로 안들어갔다. 구글링하니 @JsonFormat이니 @DateTimeFormat이니 써보래서 써봤지만 소용이 없었다.강의록 앞부분을 다시 본 결과 warehousingDate (컬럼명)과 wareHousigDate(변수명)의 차이 때문이었다. 대문자...차이..때문에... 30분은 날린 듯 하지만 다음 문제를 풀어야 해서 테이블을 다시 drop & create 후 데이터를 다시 넣어주었다. 위 API에서 가격에 대하여 int가 아니라 long을 사용한 이유는?int에 비해 long이 표현할 수 있는 숫자의 양이 더 크다고 알고 있다. 그 외에 더 있을지도 모르지만..시간 상 생략.. 문제 2. 판매여부 데이터를 넣으라고 하는 문제근데, '판매여부' 관련 컬럼이 없다.2.1 fruit 테이블에 컬럼 추가fruit 테이블에 판매여부 값을 넣을 컬럼(soldout, 매진여부)을 추가한다.bool 타입을 지원한다고 하는데, 사실상 tinyint(1)으로 저장된다기에 처음부터 tinyint(1) 형식으로 만듦처음 입고된 시점에는 soldout 되었을 리 없으므로, 0(false)를 기본값으로 넣었다.alter table `fruit` add column `soldout` tinyint(1) default 0;기본값을 0으로 설정했기에, 그 전에 들어있던 데이터들도 해당 컬럼에 0으로 들어가 있는 것을 확인할 수 있다.2.2 StoreController : sellFruit()예외처리도 배웠겠다, 해당 id의 상품이 없으면 예외처리 하란 얘기렸다?사실 sql 문으로 없으면 false를 내뱉도록 짤까 생각했지만, (이건 간단하지만) 그런 자잘한 쿼리 하나하나가 DB에 부담을 줄 것 같아서 배운대로 했다.일단은 isEmpty()를 활용했는데, 주말에는 이것 외에 다른 방법은 없는지 좀 더 공부해보자.판매 시 호출하는 함수이므로, soldout = ? 할 필요 없이 바로 soldout = 1로 주었다.  //2. 팔린 과일 정보 저장 @PutMapping("/api/v1/fruit") public void sellFruit(@RequestParam long id){ // 해당 id의 상품 존재 여부 파악 String selectSql = "SELECT * FROM fruit WHERE id = ?"; boolean fruitNotExist = jdbcTemplate.query(selectSql, (rs, rowNum) -> 0, id).isEmpty(); if(fruitNotExist){throw new IllegalArgumentException();} // 판매여부 데이터 업데이트 String updateSql = "UPDATE fruit SET soldout = 1 WHERE id = ?"; jdbcTemplate.update(updateSql, id); } 2.3 결과예시에서 1, 3번이 팔렸으므로 DB 조회 결과예외 처리 결과 문제 33.1 price 수정예제의 가격이 달라서 price 수정함update fruit set price = 3000 where id = 1; update fruit set price = 4000 where id = 2; update fruit set price = 3000 where id = 3;3.2 StoreController시간이 없어서 일단 된 곳까지 제출함근데 포스트맨으로 결과 내고나서 문제지랑 비교하니까.. 아 결과를 잘못 냈다..HTTP 응답 형식 맞게 다시 만들어야지ㅠㅠ//3. 판매/미판매 금액 조회 @GetMapping("/api/v1/fruit/stat") public List<FruitStatsResponse> descStoreInfo(){ String sql = "SELECT f.soldout, sum(f.price) as amt FROM fruit f GROUP BY f.soldout"; return jdbcTemplate.query(sql, (rs,rowNum) -> { int soldout = rs.getInt("soldout"); long amount = rs.getLong("amt"); if(soldout==1){} return new FruitStatsResponse(soldout,amount); }); } 3.3 FruitStatsResponsepublic class FruitStatsResponse { private int soldout; private long amount; public FruitStatsResponse(int soldout, long amount) { this.soldout = soldout; this.amount = amount; } public int getSoldout() { return soldout; } public long getAmount() { return amount; } } 3.4 현재 결과ㅠㅠㅠㅠ 고쳐야 함.. 

백엔드인프런워밍업클럽인프런워밍업클럽BE과제4

[인프런워밍업클럽][BE] 과제 3 | Lambda 식

1. 람다식(Lambda Expression) 이란?: 익명함수를 생성하기 위한 식 (Annoymous Function, 익명함수)1.1 람다식의 등장 배경- 복잡한 요구사항을 처리하기 위해 기존 Java 문법으로는 Method 사용이 늘어나는 등 코드의 복잡도가 높아짐- 메소드의 제한적 사용 - 객체를 통한 접근만을 허용 - 메소드 자체를 변수로 사용 불가 1.2 람다식 특징- 익명 함수 : 식별자없이 실행가능한 함수 (메소드명이 없음)- 간결한 문법- 함수형 인터페이스 지원1.3 람다식의 장/단점(1) 장점- 코드의 간결성 : 불필요한 반복문의 삭제 가능- 지연연산 수행 : 불필요한 연산 최소화- 병렬처리 기능 : 멀티쓰레드 활용- 가독성 향상 : 코드가 실제로 수행하고자 하는 로직이 추상적으로 드러남(2) 단점- 호출을 위해 직접 메소드를 불러야 함 : 람다식 생성 및 전달이 간결한 것과는 달리, 람다식 실행 시 인터페이스에 선언된 메소드 호출이 필요- 재귀 람다식 호출의 어려움 2. 람다식의 사용2.1 람다식 기본기본 형태 : 인터페이스 객체 변수명 = (매개변수, ..., 매개변수) -> {함수몸체;}구성요소매개변수 : 메소드 매개변수(parameter)하나일 경우 매개변수 또는 매개변수를 감싸는 () 생략 가능 (둘 다 생략은 안됨)화살표 : 코드 블럭을 실행(호출)메소드 구현부 (함수몸체) : {}함수몸체가 단일 실행문이면 {} 생략 가능단, 함수몸체가 return 문으로만 구성되어 있으면 {} 생략 불가 2.2 람다식 예제(추가 필요) 2.3 람다식 해석(1) 13강. GET API 람다 식 적용 전RowMapper = PreparedStatement + ResultSetJdbcTemplate.query()와 연동하여 사용SQL문의 결과값 각 행을 원하는 자료형으로 변환 : 즉, 각 행의 각 열(column)과 java 코드의 변수를 매핑시켜 줌.아래 코드에서 함수의 흐름은 다음과 같다각각 다음의 형식으로 매핑시킴long id : id bigintString name : name varchar(20)int age : age intreturn 시에는 method에서 반환값을 List<UserResponse>로 정의했으므로 UserResponse 생성자를 이용하여 구성 @GetMapping("/user") public List<UserResponse> getUsers(){ //1. SQL 조회 String sql = "SELECT * FROM users"; //2. JDBC 연결, 처리 return jdbcTemplate.query(sql, new RowMapper<UserResponse>() { @Override public UserResponse mapRow(ResultSet rs, int rowNum) throws SQLException { long id = rs.getLong("id"); String name = rs.getString("name"); int age = rs.getInt("age"); return new UserResponse(id, name, age); } }); } (2) 13강. GET API 람다 식 적용 후람다식 적용전에 비해 짧아졌으며, 중요한 부분 (매핑되는 부분)이 강조되어 보임.람다식매개변수 : rs (=ResultSet), rowNum함수본체 : 각각 java 변수와 sql 결과를 매핑시킴그러나 여전히 rs = ResultSet 이고, RowMapper 인스턴스를 사용한다는 걸 어떻게 인지하는 건지 모르겠음. @GetMapping("/user") public List<UserResponse> getUsers(){ String sql = "SELECT * FROM user"; return jdbcTemplate.query(sql, (rs, rowNum) -> { long id = rs.getLong("id"); String name = rs.getString("name"); int age = rs.getInt("age"); return new UserResponse(id, name, age); }); } 참고자료Lambda https://blog.naver.com/hj_kim97/222318922263https://blog.naver.com/it_jh/223356024460https://blog.naver.com/krkarma777/223278551937RowMapperhttps://blog.naver.com/3723578/223258910909https://mincanit.tistory.com/13

인프런워밍업클럽인프런워밍업클럽BEjavalambda식

[인프런 워밍업클럽 BE] 1일차: 어노테이션

[질문]어노테이션을 사용하는 이유 (효과) 는 무엇일까? Information for the compiler - Annotations can be used by the compiler to detect erros or suppress warnings.Compile-time and deployment-time processing - Software tools can process annotation information to generate code, XML files, and so forthRuntime processing - Some annotations are available to be examined at runtime컴파일러에 대한 정보 - 컴파일러는 주석을 사용하여 오류를 감지하거나 경고를 억제할 수 있습니다. 컴파일 시간 및 배포 시간 처리 - 소프트웨어 도구는 주석 정보를 처리하여 코드, XML 파일 등을 생성할 수 있습니다. 런타임 처리 - 런타임 시 일부 주석을 검사할 수 있습니다. 어노테이션이 가진 가장 큰 장점은 간결함이다.- 로직 흐름에 대한 컨텍스트가 응축돼 있어 적재적소에 사용된다면 불필요한 반복코드가 줄고 개발자는 비지니스 로직에 더 집중 할 수 있도록 만들어준다.어노테이션이 가진 단점- 어노테이션의 의도가 숨어있기 때문에 내부적으로 어떤 동작을 하게 되는지 명확하지 않다면 로직 플로우를 이해하기 어렵게 되고,코드정리가 덜 되어 현재 사용 되지 않고 있는 어노테이션들이 있더라도 쉽사리 누군가가 손을 대기 어렵다.하물며 ‘커스텀’ 어노테이션은 그 부담을 가중시킨다. 무분별한 어노테이션 추가가 당장의 작업 속도를 끌어올릴 순 있지만, 긴 관점에서 시의적절한 것인지를 공감할 수 있어야 한다.  나만의 어노테이션은 어떻게 만들 수 있을까? 정의: @interface키워드를 사용하여 정의@Retention(RetentionPolicy.RUNTIME) // 어노테이션 유지되는 기간을 설정 @Target(ElementType.METHOD) // 어노테이션 적용가능한 대상(동작 대상을 지정) public @interface CheckRoel { } 사용public class Roel { @CheckRoel(value = "Custom Annotation", priority = 1) public void sayHello() { // 메소드 내용 } }  빌트인(built-in) 어노테이션Java에 내장되어 있는 어노테이션으로 컴파일러를 위한 어노테이션 ◾ Override현재 메서드가 슈퍼 클래스의 메서드를 오버라이딩(overriding)한 것임을 컴파일러에게 명시해준다.메서드가 슈퍼클래스에 없다면 에러를 발생시기 때문에 오타와 같은 실수도 잡을 수 있다. ◾ Deprecated마커 어노테이션으로 다음 버전에 지원되지 않을 수도 있기 때문에 앞으로 사용하지 말라고 경고를 알린다.IDE에 취소선으로 표시됨 ◾ SuppressWarning경고를 제거하는 어노테이션으로 개발자가 의도를 가지고 설계를 했는데 컴파일은 이를 알지 못하고 컴파일 경고를 띄울 수 있기 때문에 이를 제거하는 목적이다. ◾ SafeVarargsJava 7이상에서 사용가능하고 가변인자 매개변수 사용시 경고를 무시한다 ◾ FunctionalInterfaceJava 8이상에서 사용가능하고 컴파일러에게 함수형 인터페이스라는 것을 알리는 어노테이션이다.메타 어노테이션어노테이션에 사용되는 어노테이션으로 어노테이션을 정의(설명)하기 위해 사용된다. 메타 어노테이션어노테이션에 사용되는 어노테이션으로 어노테이션을 정의하기 위해 사용 ◾ @Retention어노테이션이 유지되는 기간(Life Time)을 설정하는 어노테이션public enum RetentionPolicy { SOURCE, CLASS, RUNTIME }SOURCE : 소스파일에만 존재하고, 클래스파일에는 존재x, 컴파일러에 의해 버려진다.CLASS : 클래스파일에는 존재하지만 런타임 시에 유지할 필요 없다는 것을 알리고 이 값이 default이다.RUNTIME : 클래스파일에도 존재하고 런타임애 VM에 의해 유지되어 리플랙션을 통해 클래스 파일의 정보를 읽어 처리 가능하다. ◾ @Target어노테이션이 적용가능한 대상(동작 대상)을 지정한다.만약 다른 타입이 온다면 컴파일 에러를 띄운다.java.lang.annotation.ElementType 이라는 enum 타입이 정의 되어야 한다.이 타입은 어노테이션이 어느 곳에 적용할지 그 대상을 제한하는데 사용한다. 기존TYPE : Class, Interface(어노테이션 타입 포함), enum, jdk14에 생긴 recordFIELD : 필드 값(프로퍼티), enum 상수값METHOD : 메서드PARAMETER : 메서드 파라미터 (매개 변수)CONSTRUCTOR : 생성자LOCAL_VARIABLE : 지역 변수ANNOTATION_TYPE : 어노테이션PACKAGE : 자바 패키지jdk 1.8 이후 추가TYPE_PARAMETER : 타입 매개 변수TYPE_USE : 타입 사용 //jdk 9 이후MODULE : 모듈jdk 14이후 추가RECORD_COMPONENT : Record 컴포넌트 ◾ @documented어노테이션의 정보가 javadoc의 문서에 포함되도록 하는 어노테이션javadoc은 현재 프로젝트에 대한 api를 html 형식으로 생성해주는 도구 ◾ @Inherited자식 클래스에게도 어노테이션이 상속되도록 하는 어노테이션 ◾ @Repeatable어노테이션을 반복적으로 선언할 수 있게 하는 어노테이션

백엔드인프런워밍업클럽BE

채널톡 아이콘