


자동으로 해줘야한다
@PrePersist
public void prePersist() {
orderDate = Instant.now();
}




DTO에 새로 클래스를 만든다 .

우리가 만든 OrderRequest를 받아야 한다.
데이터베이스에 저장하려면 서비스를 통해야 하니, 서비스를 만들어야 한다.
그리고 createOrder라는 함수를 만들어 사용하는 것이 좋겠다.
그래서 지금부터 그 함수를 만들러 가겠다.

까먹기 전에 항상 어노테이션 서비스를 써주자
그리고 creatOrder을 만들자 오더의 리퀘스트를 보내주자
제이슨을 저장할건데 이건 리파지토리를 할거라 레파지토리를 만들러가야한다
우리는이제 dao 가 없다 이제 우리는 레파지 토리를 만들어줘야한다repository

레포지토리는 JPA를 상속받아 사용하는 것이다.
JPA에는 CRUD(Create, Read, Update, Delete)와 관련된 기본 함수들이 이미 다 구현되어 있기 때문에, 단순히 상속만 받아 사용하면 된다.
pom.xml 파일에 Spring 관련 의존성을 추가했기 때문에, 이를 통해 JPA를 사용할 수 있게 된 것이다.
기존에 SQL 쿼리로 작성해야 했던 데이터베이스 연산들이 이제는 자바 메서드로 제공되는 방식이 바로 JPA다.
따라서 레포지토리에서는 어떤 테이블에 데이터를 삽입할지 지정해줘야 한다.
이때 테이블 이름 대신 해당 테이블을 매핑한 엔터티 클래스를 사용하고,
제네릭 <클래스, 데이터 타입> 형식으로 프라이머리 키의 데이터 타입을 함께 명시해주는 방식이다.
이것이 JPA의 핵심 기능 중 하나다.
메서드는 우리가 직접 구현할 수도 있지만, interface를 상속받으면 기본적으로 제공되는 메서드를 활용할 수 있다.
겉으로 보기엔 아무것도 작성하지 않은 것처럼 보이지만, 이미 CRUD 관련 기능이 내장되어 있다.
추가적으로 필요할 경우, 원하는 메서드를 직접 정의해서 사용할 수도 있다.
기본적으로는 CRUD 메서드가 대부분의 데이터베이스 작업을 처리해준다.

OrderRequest는 DTO를 Order 엔터티로 변환해야 한다.
왜냐하면 save 메서드에서 Order 엔터티를 인자로 받도록 요구하고 있기 때문이다.
그래서 DTO를 엔터티로 변환하는 과정을 거치는 것이다.

여기서는 아이디가 자동 생성되기 때문에, 별도로 생성자를 만들지 않았다. 따라서 new Order() 안에 값을 바로 넣지 말고, 아래에서 각각의 값을 하나씩 설정해주는 방식으로 처리한다.

이제 잘 넣어 줬으니깐 리턴 해주면 된다.

구분을 못해서 에러를 뜬것이다. 오더가 어떤 오더인지 모르기때문에 구분을 위해서 해준다.







서비스에서는 getOrder라는 메서드를 만들고, Long 타입의 아이디를 받아서 데이터베이스에서 해당 데이터를 조회하도록 한다.
findAll이 아니라 특정 아이디로 데이터를 가져오는 메서드를 사용해야 한다.
아이디로 조회하는 것이므로, 결과는 하나의 행만 반환될 것이다.
데이터베이스에서 가져온 Order 엔터티가 존재할 수도 있고, 존재하지 않을 수도 있으므로 Optional을 사용해야 한다.
Optional은 값이 있을 수도, 없을 수도 있기 때문에 if-else 문을 사용하여 처리할 수 있다.
데이터가 없는 경우, throw를 사용해 예외를 던지고, 이를 통해 에러 코드를 반환할 수 있다.
이 예외는 컨트롤러에서 받아서 처리하게 된다.
예외를 던질 때는 메모리 상에 객체를 생성하고, 이를 힙 메모리에 저장한 후 던져주므로, 해당 에러를 컨트롤러가 받아 처리해야 한다.
이는 데이터가 비정상적인 경우에 해당한다.
정상적으로 데이터를 조회한 경우, if를 사용하여 데이터가 존재할 때의 로직을 작성하면 된다.
그리고 엔터티를 그대로 반환하지 않고, DTO로 변환하여 클라이언트에 전달해야 한다.
따라서 OrderResponse라는 DTO를 새로 생성하고, 조회한 Order 데이터를 OrderResponse로 변환하는 과정을 추가한다.
마지막으로 OrderResponse 데이터 타입과 public 키워드를 지정한 메서드를 작성하고, 변환된 데이터를 컨트롤러로 넘기면 된다.

컨트롤러를 마무리해준 뒤에 확인해주면 된다

완성
아래는 더 세련된 방식으로, 익셉션(예외)을 사용하는 방법이다.
익셉션(예외)은 프로그램 실행 중 발생할 수 있는 오류 상황을 처리하기 위해 사용하는 기능으로, 코드의 가독성을 높이고 오류를 명확하게 전달할 수 있게 해준다.


근데 이거 안만들어도 throw new RuntimeException(); 을 써도 된다. 기본적으로 제공되는 것이기에 이것 만 쓰도 된다





아이디는 Long 타입이고, 콤마 하나 더 붙여서 요청 바디에 JSON 데이터가 들어온다. 그래서 @RequestBody를 사용하고, 이전에 만들어둔 OrderRequest DTO를 활용하면 된다. 함수의 파라미터는 두 개가 필요하다.
이 데이터를 OrderService로 넘겨야 하니, OrderService에 updateOrder라는 함수를 만들어서 아이디와 OrderRequest를 함께 전달하는 방식이 좋겠다.
이제 서비스 로직을 작성하러 가겠다.

DB에서 데이터를 가져와서, 클라이언트가 원하는 방식으로 수정한 후 다시 저장하는 작업을 할 것이다.
먼저 클라이언트가 데이터를 보낸다.
클라이언트가 Long 타입의 ID와 OrderRequest라는 데이터를 보낸다.
이 데이터를 받아서 기존의 주문 정보를 업데이트할것이다
먼저 서비스에서 DB에서 해당 데이터를 가져온다.
OrderRepository를 이용해, 해당 ID에 해당하는 주문 데이터를 가져와야 한다.
그런데 해당 ID가 DB에 없을 수도 있으니까, Optional을 사용해 안전하게 검사한다.
만약 데이터가 존재하지 않는다면 RuntimeException을 발생시켜서 처리할 예정이다.
데이터 수정하기
데이터를 찾았으면, 가져온 데이터를 savedOrder라는 변수에 담는다.
savedOrder의 productName과 같은 필드를, 클라이언트가 보낸 OrderRequest 데이터로 수정한다.
하지만 ID와 주문 날짜(orderDate)는 변경하지 않는다. (이미 고유한 값이기 때문에)
DB에 다시 저장하기
수정이 끝난 데이터를 OrderRepository.save() 메서드를 사용해 DB에 다시 저장한다.
리턴할 값이 없으니까, void 메서드로 처리했다.
예외 처리는 이렇게 한다.
만약 해당 ID의 주문이 없을 경우, RuntimeException을 던지도록 했다.
컨트롤러에서 이 예외를 받아서 ResponseEntity를 사용해 HTTP 상태 코드와 에러 메시지를 클라이언트에 반환하게 했다.
필요하면 클라이언트의 요구사항에 맞게 에러 메시지를 바꿀 수도 있다.

예외를 던져주면 그걸 받아줄 문법이 필요하니까 try-catch를 사용해준다.
그리고 예외를 잡은 후, return을 사용해서 API 명세에 맞게 응답을 돌려준다.





existsById를 사용하면 해당 아이디가 존재하는지 여부를 확인해준다.
만약 false라면 throw를 사용해 예외를 던져주자.
현재는 삭제 작업이므로 데이터를 가져올 필요는 없지만, 존재 여부는 반드시 체크해야 한다.
deleteById와 deleteAll을 사용하면 모든 데이터가 삭제되기 때문에, 매우 주의해야 한다.

다시 컨트롤러로 돌아와서, 예외를 던졌을 때 받을 수 있도록 try-catch를 사용한다.
그 후, 클라이언트에게 응답을 반환해주면 된다. (API 명세서를 참고)




방법1


이렇게 직접 처리하는 것은 번거로우므로, Pageable을 사용하여 보다 간편하게 구현하는 방식을 선택하겠다.

String[] orderArray =order.split(",");// ,로 나눠준다.
Sort.Direction direction =Sort.Direction.fromString( orderArray[1]);// desc or asc 만드는 방법
Sort sort = Sort.by(direction, orderArray[0]);// 정렬을 만들어준다.
컨트롤러 만들었으니 서비스로 이동하겠다

이거 하면 알아서 페이져블 알아서 끊어서 가져와줌





준비됬어 이제 컨트롤러가서 데이터 담아주겠어


방법2)


orderRepository.findAll()을 사용하면, 데이터가 수십만에서 수백만 건에 이를 경우 메모리 과부하가 발생할 수 있다. 데이터가 적을 때는 문제가 없지만, 대량 데이터를 다룰 때는 페이징을 사용하는 것이 필요하겠다.
PageRequest 객체를 생성할 때는 생성자를 직접 사용하는 대신 PageRequest.of()를 사용하는 것이 올바르겠다.
예를 들어, "orderDate,desc"와 같은 정렬 조건이 문자열로 주어질 경우, 이를 기준과 방향으로 나누어 사용해야 하겠다. 해당 문자열을 **콤마(,)**로 나누어 첫 번째 값은 정렬 기준, 두 번째 값은 정렬 방향으로 해석할 수 있겠다.
orderArray[0]: "orderDate" (정렬 기준)
orderArray[1]: "desc" (정렬 방향)
따라서 Sort 객체를 생성할 때, 아래와 같이 처리할 수 있겠다.
java
코드 복사
Sort sort = Sort.by(Sort.Direction.DESC, "id");
findAll()을 사용하기 위해서는 PageRequest와 함께 Sort가 필요하므로, 위에서 Sort 객체를 먼저 생성한 것이다.

필요하니깐 가서 리스펀스만들어주기
selsct*
from order
order by oeder_date desc
limit 0,3;
이렇게 나오는 것이
Page<Order>orderPage = orderRepository.findAll(pageRequest);
이제 여기에 데이터를 담아줄 것이다. 데이터를 담을 때는 반복문을 사용하여 담아줄 계획이다.
각 변수를 포함하고 있는 Order 객체에서, 일대일로 매칭되는 클래스를 가져와야 하므로, 해당 작업을 수행하기 위해 for문을 사용하겠다.


OrderItemResponse orderItemResponse = new OrderItemResponse();
// 새로운 객체 생성해준다. 여기에 저장해줄 것이다
그리고 이제 데이터를 하나씩 저장할 것이다. savedOrder는 데이터베이스의 한 행(row)을 의미한다.
각 행에 들어 있는 id 값을 활용하여 DTO의 id에 값을 할당해줄 것이다.
이 과정은 결국 JSON 데이터를 생성하는 것이다.
단, id만 저장할 수 없으니, 나머지 필요한 데이터도 모두 함께 저장해줄 것이다.
savedOrder는 하나의 데이터 행을 의미하며, 이를 기반으로 필요한 정보를 저장하고 객체를 생성하는 것이다.
시간 정보는 자바에서 Instant 타입을 사용했지만, 데이터를 문자열로 전송해야 하기 때문에 toString() 메서드를 사용하여 변환해주었다.
이렇게 DTO를 완성한 후, 정보를 모두 담은 DTO 객체를 리스트에 하나씩 추가해줄 것이다.
그 과정이 바로 다음 코드에서 수행되는 것이다.
orderList.add(orderItemResponse);
반복문이 모두 완료되었다는 것은 CPU가 모든 연산을 마친 상태를 의미한다.
CPU의 부하가 내려갔다는 것은 모든 DTO가 생성되어 리스트에 추가되었음을 뜻한다.
이제 orderList만 가지고 있으면 된다. 이 리스트는 모든 데이터를 포함하고 있으므로, 데이터 준비가 완료된 상태이다.
이제 남은 것은 **페이지 정보(PageInfo)**를 준비하는 것이다.
데이터를 JSON 형식으로 변환해야 하므로, 이를 클래스로 변환할 필요가 있다.
따라서 DTO에서 필요한 정보를 활용하여 PageInfo 클래스를 생성해줄 것이다.

보내려면 저장해줘야한다.
디티오 여기에 데이타 담아야하니깐 다시 서비스로 가서

페이징 정보를 담을 DTO가 필요하다 따라서 만들어야한다 뉴 페이지 인포해서 만들어주는 것이다
orderRepository를 통해 SELECT 쿼리를 실행해야 한다.
이전에 orderRepository가 이미 존재하고 있으므로, 이를 사용하여 데이터를 조회할 수 있다.
orderPage는 자동으로 페이징 처리된 데이터를 제공하는 객체로, 페이지 계산을 포함한 데이터를 반환해준다.
하지만 데이터가 너무 많을 경우, int 타입으로는 모든 데이터를 수용할 수 없다.
데이터가 매우 많아질 가능성이 있기 때문에, 이를 대비해 long 타입을 사용하는 것이다.
이제 통으로 줄 오더 리스트 리스판스만들어준다

API 명세서를 보고 전체 담을 리스판스를 만들어준다. 이제 서비스가서 데이터처리해준다




'Spring Boot JPA > 실습' 카테고리의 다른 글
여행코스 공유 플랫폼 JPA (0) | 2025.01.09 |
---|---|
JPA Join과 Config 설정으로 데이터베이스 관계 정리2 (0) | 2025.01.08 |
JPA Join과 Config 설정으로 데이터베이스 관계 정리 (0) | 2025.01.07 |
AI를 활용한 화면 만들기 (1) | 2025.01.07 |
JPA 실습 : 효율적인 데이터 관리 (1) | 2025.01.03 |