@RestController
@RequiredArgsConstructor
@Slf4j
public class JpaRestApiController {
private final MemberService memberService;
//postman - >body->raw -> json
//@RequestBody : Json(member)으로 온것을 --> Member member Setteing
//회원가입
@PostMapping("/restApi/v1/memberSave")
public CreateMemberResponse saveMemberV1(@RequestBody @Valid Member member) {
System.out.println("JpaRestApiController /api/v1/memberSave member.getName()->"+member.getName());
log.info("cmember.getSal()-> {}.", member.getSal());
Long id = memberService.saveMember(member);
return new CreateMemberResponse(id);
}
// 목적 : Entity Member member를 직접 사용 금지 --> 직접 (화면이나 API를 위한 Setting 금지)
// 예시 : @NotEmpty --> @Column(name = "userName")
@PostMapping("/restApi/v2/memberSave")
public CreateMemberResponse saveMemberV2(@RequestBody @Valid CreateMemberRequest cMember) {
log.info("/restApi/v2/memberSave cMember.getName()->{}",cMember.getName());
log.info("/restApi/v2/memberSave cMember.getSal()->{}",cMember.getSal());
Member member = new Member();
member.setName(cMember.getName());
member.setSal(cMember.getSal());
Long id = memberService.saveMember(member);
return new CreateMemberResponse(id);
}
@Data
static class CreateMemberRequest{
@NotEmpty
private String name;
private Long sal;
}
@Data
@RequiredArgsConstructor
class CreateMemberResponse {
private final Long id;
// public CreateMemberResponse(Long id) {
// this.id = id;
// }
}
//수정 api
// PUT 방식을사용했는데, PUT은 전체 업데이트를 할 때 사용
//* URI 상에서 '{ }' 로 감싸여있는 부분과 동일한 변수명을 사용하는 방법
//해당 데이터가 있으면 업데이트를 하기에
// * PUT요청이 여러번 실행되어도 해당 데이터는 같은 상태이기에 멱등
@PutMapping("/restApi/v21/members/{id}")
public UpdateMemberResponse updateMemberV21(@PathVariable("id") Long id ,
@RequestBody @Valid UpdateMemberRequest uMember) {
System.out.println("updateMemberV21 id ->"+id);
memberService.updateMember(id, uMember.getName(), uMember.getSal());
Member findMember = memberService.findByMember(id);
return new UpdateMemberResponse(findMember.getId(),findMember.getName(),findMember.getSal());
}
@Data
static class UpdateMemberRequest {
private String name;
private Long sal;
}
@Data
@AllArgsConstructor
class UpdateMemberResponse{
private Long id;
private String name;
private Long sal;
}
// 회원가입 API
public Long saveMember(@Valid Member member) {
System.out.println("MemberService join member.getName()->"+member.getName());
Long id = memberRepository.save(member);
return id;
}
//회원수정
public void updateMember(Long id, String name, Long sal) {
Member member = new Member();
member.setId(id);
member.setName(name);
member.setSal(sal);
System.out.println("MemberService updateMember member.getName()--> " +member.getName());
System.out.println("MemberService updateMember member.getSae()--> " +member.getSal());
memberRepository.updataByMember(member);
return;
}
//회원조회
public Member findByMember(Long memberId) {
Member member = memberRepository.findByMember(memberId);
return member;
}
package com.oracle.oBootJpaApi01.repository;
import java.util.List;
import com.oracle.oBootJpaApi01.domain.Member;
public interface MemberRepository {
Long save(Member member);
List<Member> findAll();
int updataByMember (Member member);
Member findByMember(Long memberId);
}
package com.oracle.oBootJpaApi01.repository;
import java.util.List;
import javax.persistence.EntityManager;
import org.apache.tomcat.jni.Mmap;
import org.springframework.stereotype.Repository;
import com.oracle.oBootJpaApi01.domain.Member;
import lombok.RequiredArgsConstructor;
@Repository
@RequiredArgsConstructor
public class JpaMemberRepository implements MemberRepository {
private final EntityManager em;
@Override
public Long save(Member member) {
System.out.println("JpaMemberRepository save before...");
em.persist(member);
return member.getId();
}
@Override
public List<Member> findAll() {
List<Member> memberList = em.createQuery("select m from Member m", Member.class)
.getResultList();
System.out.println("JpaMemberRepository findAll memberList.size()->"+memberList.size());
return memberList;
}
@Override
public int updataByMember(Member member) {
int result= 0;
Member member3 = em.find(Member.class, member.getId());
if(member3 != null) {
//회원저장
member3.setName(member.getName());
member3.setSal(member.getSal());
result=1;
}else {
result=0;
System.out.println("JpaMemberRepository updataByMember No Exist... ");
}
return 0;
}
@Override
public Member findByMember(Long memberId) {
Member member = em.find(Member.class, memberId);
return member;
}
}
▶oBootJpa에서 domian 가져옴
▶복잡한 oders 조회 하기
package com.oracle.oBootJpaApi02.domain;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import com.oracle.oBootJpaApi02.domain.item.OrderItem;
import lombok.Data;
@Entity
@Table(name = "orders")
@Data
public class Order {
@Id
@GeneratedValue
@Column(name = "order_id")
private Long id;
// Member Entity의 member_id에 의해 연결
//@ManyToOne(fetch = FetchType.LAZY)
@ManyToOne //다대일관계
@JoinColumn(name = "member_id")
private Member member;
//배송정보
//@OneToOne(fetch = FetchType.LAZY)
@OneToOne
@JoinColumn(name = "delivery_id")
private Delivery delivery; //관계 객체
//주문시간
private LocalDateTime orderDate;
//주문상태[ORDER,CANCLE]
@Enumerated(EnumType.STRING) //무조건 String으로 잡기
private OrderStatus status;
//---------------------------------------------------------------------
//OrderItem Entity의 order_id field의 의해서 mapper당함 --> 읽기 전용
@OneToMany(mappedBy = "order" )
private List<OrderItem> orderItems = new ArrayList<>();
//---------------------------------------------------------------------
//==연관 관계 메서드 ==//
public void setMember(Member member) {
this.member = member;
member.getOrders().add(this);
}
public static Order createOrder(Member member, Delivery delivery ) {
Order order = new Order();
order.setMember(member);
order.setDelivery(delivery);
order.setStatus(OrderStatus.ORDER);
order.setOrderDate(LocalDateTime.now());
return order;
}
}
package com.oracle.oBootJpaApi02.controller;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.oracle.oBootJpaApi02.dto.SimpleOrderDto;
import com.oracle.oBootJpaApi02.dto.api.OrderDto;
import com.oracle.oBootJpaApi02.service.OrderService;
import lombok.RequiredArgsConstructor;
@RestController
@RequiredArgsConstructor
public class OrderRestApiController {
private final OrderService orderService;
//M:1 엔티티를 조회해서 DTO로 변환 (fetch join사용x)
//단점 : 관련 쿼리 n번 호출
@GetMapping("/restApi/ordersV21")
public List<SimpleOrderDto> ordersV21(){
List<SimpleOrderDto> result = null;
System.out.println("/restApi/ordersV21/ Start . . . ");
result = orderService.serviceOrdersV21();
return result;
}
//M:1 엔티티를 조회해서 DTO로 변환 (fetch join사용x)
//단점 : 관련 쿼리 n번 호출
//M:1 & 1: M Entity 포함, 조회 해서 DTO변환
@GetMapping("/restApi/ordersV22")
public List<OrderDto> ordersV22(){
List<OrderDto> result = null;
System.out.println("/restApi/ordersV22/ Start . . . ");
result = orderService.serviceOrdersV22();
return result;
}
}
package com.oracle.oBootJpaApi02.service;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.oracle.oBootJpaApi02.domain.Order;
import com.oracle.oBootJpaApi02.dto.SimpleOrderDto;
import com.oracle.oBootJpaApi02.dto.api.OrderDto;
import com.oracle.oBootJpaApi02.repository.OrderRepository;
import lombok.RequiredArgsConstructor;
@Service
@Transactional
@RequiredArgsConstructor
public class OrderService {
private final OrderRepository orderRepository;
public List<SimpleOrderDto> serviceOrdersV21() {
System.out.println("serviceOrdersV21 Start . . . . ");
List<Order> orders = orderRepository.findAll();
List<SimpleOrderDto> result = orders.stream()
.map(o -> new SimpleOrderDto(o))
.collect(Collectors.toList());
System.out.println("OrderService result.size()-->"+result.size());
return result;
}
public List<OrderDto> serviceOrdersV22() {
System.out.println("serviceOrdersV22 Start . . . . ");
List<Order> orders = orderRepository.findAll();
List<OrderDto> result = orders.stream()
.map(o -> new OrderDto(o))
.collect(Collectors.toList());
System.out.println("OrderService result.size()-->"+result.size());
return result;
}
}
package com.oracle.oBootJpaApi02.repository;
import java.util.List;
import javax.persistence.EntityManager;
import org.springframework.stereotype.Repository;
import com.oracle.oBootJpaApi02.domain.Order;
import lombok.RequiredArgsConstructor;
@Repository
@RequiredArgsConstructor
public class OrderRepository {
private final EntityManager em;
public List<Order> findAll() {
List<Order> orderList = em.createQuery("select o from Order o ", Order.class)
.getResultList();
return orderList;
}
}
order.java보고 필요한것 가져오기
package com.oracle.oBootJpaApi02.dto;
import java.time.LocalDateTime;
import com.oracle.oBootJpaApi02.domain.Address;
import com.oracle.oBootJpaApi02.domain.Order;
import com.oracle.oBootJpaApi02.domain.OrderStatus;
import lombok.Data;
@Data
public class SimpleOrderDto {
private Long orderId;
private String name;
private LocalDateTime orderDate; //주문시간
private OrderStatus orderStatus;
private Address adderss;
public SimpleOrderDto(Order order) {
orderId =order.getId();
name = order.getMember().getName();
orderDate = order.getOrderDate();
orderStatus = order.getStatus();
adderss = order.getDelivery().getAddress();
}
}
package com.oracle.oBootJpaApi02.dto.api;
import java.util.List;
import java.util.stream.Collectors;
import com.oracle.oBootJpaApi02.domain.Address;
import com.oracle.oBootJpaApi02.domain.Order;
import com.oracle.oBootJpaApi02.domain.OrderStatus;
import lombok.Data;
@Data
public class OrderDto {
private Long orderId;
private String name;
private LocalDateTime orderDate; //주문시간
private OrderStatus orderStatus;
private Address adderss;
//1 : M 관계추가
private List<OrderItemDto> orderItems;
public OrderDto(Order order) {
orderId =order.getId();
name = order.getMember().getName();
orderDate = order.getOrderDate();
orderStatus = order.getStatus();
adderss = order.getDelivery().getAddress();
//일대 다이기 때문에
stream을 쓰면 내부에서 for 문을 돈다
나를 호출한놈의 몸에 들어감 -> restcontroller
orderItems = order.getOrderItems().stream()
.map(orderItem->new OrderItemDto(orderItem))
.collect(Collectors.toList());
//여기까지 조회를 할거야 하고 짤라주어야함 .
}
}
package com.oracle.oBootJpaApi02.dto.api;
import com.oracle.oBootJpaApi02.domain.item.OrderItem;
import lombok.Data;
@Data
public class OrderItemDto {
private String itemName; //상품명
private int orderPrice; //주문가격
private int count ; // 주문수량
public OrderItemDto(OrderItem orderItem) {
itemName= orderItem.getItem().getName();
orderPrice = orderItem.getOrderPrice();![](https://velog.velcdn.com/images/rhdguswlx/post/a7ff724d-6a85-4caa-aec8-97a93bc21b65/image.png)
count = orderItem.getCount();
}
}
▶postman 에서 url 확인 실행
M:1 엔티티를 조회해서 DTO로 변환 (fetch join사용 O )
단점 : 관련 쿼리 n번 호출 문제 해결
많은 Query로 인한 성능 저하 개선
@GetMapping("/restApi/ordersV31")
public List<SimpleOrderDto> ordersV31(){
List<SimpleOrderDto> result = null;
System.out.println("/restApi/ordersV31/ Start . . . ");
result = orderService.serviceOrdersV31();
return result;
}
public List<SimpleOrderDto> serviceOrdersV31() {
System.out.println("serviceOrdersV31 Start . . . . ");
List<Order> orders = orderRepository.findAllWithItem();
List<SimpleOrderDto> results = orders.stream()
.map(o -> new SimpleOrderDto(o))
.collect(Collectors.toList())
;
return results;
}
Query 한방 --> 성능이 월등하게 향
단점 : 페이징이 불가능하다
//Jpa에서만 지원하는 기능
//fetch Join
//Lazy--> fetch Join
public List<Order> findAllWithItem() { //오덜 객체 관점
List<Order> findOrders = em.createQuery("select distinct o from Order o "
+ " join fetch o.member m "
+ " join fetch o.delivery d "
+ " join fetch o.orderItems oi"
+ " join fetch oi.item i ", Order.class
).getResultList();
System.out.println(" OrderRepository findAllWithItem start . . +findOrders.size()--> "+findOrders.size());
return findOrders;
}
}
▶한큐에 모든것을 가지고 온다
엔티티 를 조회해서 Dto 로 변환 (fetch join 사용 o) 1:M 추가
fetch join으로 쿼리 1번 호출
많은 Query로 인한 성능 저하 개선
@GetMapping("/restApi/ordersV32")
public List<OrderDto> ordersV32(){
List<OrderDto> result = null;
System.out.println("/restApi/ordersV32/ Start . . . ");
result = orderService.serviceOrdersV32();
return result;
}
public List<OrderDto> serviceOrdersV32() {
System.out.println("serviceOrdersV32 Start . . . . ");
List<Order> orders = orderRepository.findAllWithItem();
List<OrderDto> results = orders.stream()
.map(o -> new OrderDto(o))
.collect(Collectors.toList())
;
System.out.println("serviceOrdersV32 results.size()-->"+results.size());
return null;
}