20221107-72 JPA REST api(2) 회원가입/수정/조회/fetch Join

공현지·2022년 11월 7일
0

spring

목록 보기
16/30
post-thumbnail

회원가입

회원수정

회원조회

JpaRestApiController

 
@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;
	       
	  }
	    
        
        
     
     
     

MemberService

	// 회원가입 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;
	 
	 
 }
	

MemberRepository

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);
   
}

JpaMemberRepository

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;
	}

}



oBootJpaApi02


▶oBootJpa에서 domian 가져옴

▶복잡한 oders 조회 하기

Order.java --> 전부(fetch = FetchType.EAGAR)

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;
			
		}
		
}


OrderRestApiController

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;
		 
		 
	 }
	 
}

OrderService

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;
}
}

OrderRepository

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;
	}
	  

		  
	  }
 
	  




SimpleOrderDto

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();
		
	}
}


OrderDto

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());
		//여기까지 조회를 할거야 하고 짤라주어야함 . 
		}
}

OrderItemDto

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 확인 실행

Order.java --> (fetch = FetchType.LAZY ) 성능개선

M:1 엔티티를 조회해서 DTO로 변환 (fetch join사용 O )
단점 : 관련 쿼리 n번 호출 문제 해결
많은 Query로 인한 성능 저하 개선

OrderRestApiController

@GetMapping("/restApi/ordersV31")
	 public List<SimpleOrderDto> ordersV31(){
		 		List<SimpleOrderDto> result = null;
		 		
		 		System.out.println("/restApi/ordersV31/ Start . . . ");
		 		result = orderService.serviceOrdersV31();
		 		return result;
		 
		 
	 }

OrderService

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;
}

OrderRepository (fetch Join)

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;
	}
	  

		  
	  }

▶한큐에 모든것을 가지고 온다


OrderRestApiController

엔티티 를 조회해서 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;
		 
		 
	 }

OrderService


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;
	}

0개의 댓글