20221102-69 Spring Boot(5)JPA쇼핑몰만들기/상품주문/주문내역 /상품주문/주문내역목록보기

공현지·2022년 11월 2일
0

spring

목록 보기
13/30

상품목록수정

ItemController

 //상품목록수정
	@PostMapping(value = "/items/{itemId}/edit") 
	public String updateItem(@ModelAttribute("form")BookForm form) {
		log.info("updateItem itemId->{}",form.getId());
		log.info("updateItem getName->{}",form.getName());
		// 1. [controller-->Service ]-->updateItem(id, name , price)
        // 2. [Service   -->Repository ]--> 수정
	   //방법2
		//itemService.updateItem(form.getId(), form.getName(),form.getPrice());
	 
	
	  itemService.updateItem(form);
		
		
		 return "redirect:/items";
		

Itemservice


//상품수정
public void updateItem(BookForm form) {
	Item item = itemRepository.findOne(form.getId());
	item.setName(form.getName());
	item.setPrice(form.getPrice());
	
}
	

@Transactional (readOnly = true)??

조회한 데이터를 return 한다고 해도 의도치 않게 데이터가 변경되는 일을 사전에 방지해줍니다. (성능향상)


상품주문화면

OrderController

package com.oracle.oBootJpa03.controller;

import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import com.oracle.oBootJpa03.domain.Member;
import com.oracle.oBootJpa03.domain.item.Item;
import com.oracle.oBootJpa03.service.ItemService;
import com.oracle.oBootJpa03.service.MemberService;
import com.oracle.oBootJpa03.service.OrderService;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Controller
@Slf4j
@RequiredArgsConstructor
public class OrderController {
   private final OrderService orderService;
   private final MemberService memberService;
   private final ItemService itemService;
   
   
   // 회원, 아이템 불러오기
   @GetMapping(value = "/order")
   public String createOrderForm(Model model) {
      log.info("OrderController createOrderForm Start...");
      List<Member> members = memberService.findMembers();
      List<Item>     items = itemService.findItems();
      model.addAttribute("members", members);
      model.addAttribute("items", items);
      return "order/orderForm";
   }
   
   // OrderController -> orderSave
}

OrderService

package com.oracle.oBootJpa03.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.oracle.oBootJpa03.repository.ItemRepository;
import com.oracle.oBootJpa03.repository.MemeberRepository;
import com.oracle.oBootJpa03.repository.OrderRepository;

import lombok.RequiredArgsConstructor;

@Service
@Transactional
@RequiredArgsConstructor //생성자 자동생성
public class OrderService {

			private final OrderRepository orderRepository;
			private final MemeberRepository memeberRepository;
			private final ItemRepository itemRepository;
}

OrderRepository

package com.oracle.oBootJpa03.repository;

import javax.persistence.EntityManager;

import org.springframework.stereotype.Repository;

import lombok.RequiredArgsConstructor;

@Repository
@RequiredArgsConstructor  //생성자 자동생성
public class OrderRepository {
  private final EntityManager em;
}

상품주문

🔽밑 표 보고 OrderItem 작성하기

//객체명 : order_item_seq
//DB SEQ : order_item_sequence
//Table : order_item

OrderItem

package com.oracle.oBootJpa03.domain.item;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

import org.springframework.data.mapping.AccessOptions.GetOptions.GetNulls;

import com.oracle.oBootJpa03.domain.Order;

import lombok.Data;
//객체명  : order_item_seq
//DB SEQ : order_item_sequence
//Table    : order_item

@Entity
@Data
@SequenceGenerator(name = "order_item_seq" ,
				sequenceName = "order_item_sequence",
				initialValue = 1,
				allocationSize = 1 
		)			
@Table(name = "order_item")
public class OrderItem {
	
	protected OrderItem() {
		
	}
	
  @Id 
  @GeneratedValue(strategy = GenerationType.SEQUENCE,
  							generator = "order_item_seq"
	                     )
  
  	@Column(name = "order_item_id")	
	private Long id;
	
  @ManyToOne
  @JoinColumn(name = "item_id")
  private Item item;    //주문상품
  @ManyToOne
  @JoinColumn(name = "order_id")
  private Order order;   //주문
	
  
  private int orderPrice;		//주문가격
  private int count;			//주문수량 
	
//생성 메서드( createOrderItem() ): 주문 상품, 가격, 수량 정보를 사용해서 주문상품 엔티티를 생성

  public static OrderItem createOrderItem(Item item, int orderPrice, int count) {
	  	OrderItem orderItem = new OrderItem();
	  	orderItem.setItem(item);
	  	orderItem.setOrderPrice(orderPrice);
	  	orderItem.setCount(count);
	  	//필요시 재고 처리 
	  	//item.removeStock(count)
	  	
	  	return orderItem;
	  
  }
	
	

OrderController

 //상품주문
   
   @PostMapping(value = "/orderSave")
   public String orderSave(@RequestParam("memberId") Long memberId,
		   						@RequestParam("itemId") Long itemId,
		   						@RequestParam("count") int count  ) {
	   log.info("Order orderSave Start...");
	   orderService.order(memberId, itemId, count);
	   return "redirect:/";
	   
	   
   }
   

public Member findOne(Long id) {
// 원래방법 Member member = em.find(Member.class, id);
// return member;
//한번에 보내기
return em.find(Member.class, id);

추가 코딩

> order.java

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

OrderService


package com.oracle.oBootJpa03.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.oracle.oBootJpa03.domain.Delivery;
import com.oracle.oBootJpa03.domain.DeliveryStatus;
import com.oracle.oBootJpa03.domain.Member;
import com.oracle.oBootJpa03.domain.Order;
import com.oracle.oBootJpa03.domain.item.Item;
import com.oracle.oBootJpa03.domain.item.OrderItem;
import com.oracle.oBootJpa03.repository.ItemRepository;
import com.oracle.oBootJpa03.repository.MemeberRepository;
import com.oracle.oBootJpa03.repository.OrderRepository;

import lombok.RequiredArgsConstructor;

@Service
@Transactional
@RequiredArgsConstructor //생성자 자동생성
public class OrderService {

			private final OrderRepository orderRepository;
			private final MemeberRepository memeberRepository;
			private final ItemRepository itemRepository;
			//1.  Delivery   Save
			//2.  Order      Save
			//3.  OrderItem Save
			//4. 재고 --> X, OrderItem은 하나만 처리 
			public void order(Long memberId, Long itemId, int count) {
			//엔티티 조회 
		    Member member = memeberRepository.findOne(memberId);
		   Item item = itemRepository.findOne(itemId);
		  
		   //1. 주문(배송)정보 생성(Member 주소 배송 가정)
		   Delivery delivery = new Delivery();
		   delivery.setAddress(member.getAddress());
		   delivery.setStatus(DeliveryStatus.READY);
				
		   //주문(배송)정보 저장 
		   orderRepository.saveDelivery(delivery);
		   System.out.println(" OrderService delivery.getId()-> "+delivery.getId());
		   System.out.println(" OrderService item.getId()-> "+item.getId());
		   System.out.println(" OrderService member.getId()-> "+member.getId());
		  
		   // 2- 1,주문생성
		   Order order= Order.createOrder(member, delivery);
		   //2-2 주문저장
		  orderRepository.saveOrder(order);
		  //3. 주문상품 생성
		  //OrderItem orederItem - new OrderItem();  --연관관계 Mapping 처리 위해
		  OrderItem orderItem = OrderItem.createOrderItem(item, item.getPrice(), count);
          //전시용,위에다편입
		  orderItem.setOrder(order);
		  orderRepository.saveOrderItem(orderItem);
		  
		  
			}
}


OrderRepository



package com.oracle.oBootJpa03.repository;

import javax.persistence.EntityManager;

import org.springframework.stereotype.Repository;

import com.oracle.oBootJpa03.domain.Delivery;
import com.oracle.oBootJpa03.domain.Order;
import com.oracle.oBootJpa03.domain.item.OrderItem;

import lombok.RequiredArgsConstructor;

@Repository
@RequiredArgsConstructor  //생성자 자동생성
public class OrderRepository {
  private final EntityManager em;

  //주문(배송)정보 저장 
public void saveDelivery(Delivery delivery) {
	em.persist(delivery);
	
	
}
//2-2 주문저장
public void saveOrder(Order order) {
	em.persist(order);

	
}
//3. 주문상품 생성
public void saveOrderItem(OrderItem orderItem) {
	em.persist(orderItem);
	
}
}

주문내역 목록보기

  1. Controller
    method-->orderList (OrderSearch, Model)
  2. Controller--> Service
    method-->findOrders();
  3. Service --> Repository
    method-->findAll();

Orderlist.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
		<div class="container">
		<table  border="1">
		<thead>
 	<tr>
 		<th>#</th>
 		<th>회원명</th>
 		<th>배송지</th>
 		<th>상태</th>
 		<th>일시</th>
 	</tr>
 	</thead>
 	<tbody>
 	<tr th:each="order : ${orders}" >
 	      <td th:text="${order.id}"></td>
 	      <td th:text="${order.member.name}"></td>
 	     <td th:text="${order.delivery.address.city}"></td>
 	     <td th:text="${order.status}"></td>
 		<td th:text="${order.orderDate}"></td>
    </tr>
 	</tbody>	
     </table>
	</div>

</body>
</html>

OrderController

   //주문내역 
       @GetMapping(value = "/orders")
       public String orderList(  OrderSearch orderSearch  ,Model model) {
       System.out.println("OrderController orderList . . . ");
       List<Order> orders = orderService.findOrders();
       model.addAttribute("orders", orders);
       return "order/orderList";
    	   
       }

OrderService

	//주문내역 목록보기   
			public List<Order> findOrders() {
				List<Order> findorderList = orderRepository.findAll();
				System.out.println("OrderRepository findorderList.size()->"+findorderList.size());

				return findorderList;
			}

OrderRository


//주문내역 목록보기  
public List<Order> findAll() {
	
	return em.createQuery("select o from Order o", Order.class)
					.getResultList();
}

업로드중..

즉시로딩(EAGER)과 지연로딩(LAZY) 왜 LAZY 로딩을 써야할까?

실제 @ManyToOne의 경우 FK쪽의 엔티티를 가져올 때 PK쪽의 엔티티도 같이 가져오게 되는데요, 이러한 과정이 꼭 필요한건지, 필요하지 않다면 어떻게 해결할 수 있는지

  • 특정 엔티티를 조회할 때 연관된 모든 엔티티를 같이 로딩하는 것을 즉시 로딩(Eager Loading)이라고 합니다
  • 지연 로딩(Lazy Loading)이란, 가능한 객체의 초기화를 지연시키는데 사용하는 패턴입니다.
  • 이와 같은 즉시 로딩은 연관된 엔티티를 모두 가져온다는 장점이 있지만,
    실무에서 엔티티간의 관계가 복잡해질수록 조인으로 인한 성능 저하를 피할 수 없게 됩니다.
  • '즉시 로딩'은 불필요한 조인까지 포함해서 처리하는 경우가 많기 때문에 '지연 로딩'의 사용을 권장하고 있습니다.
  • (보편적으로 '지연 로딩'을 기본으로 사용하고, 상황에 맞게 필요한 방법을 찾는것이 좋은 것 같습니다 😃)
  • 재연결이 필요한데, @Transactional 어노테이션을 통해 해결할 수 있습니다.

0개의 댓글