ItemController @GetMapping(value = {"/admin/items", "/admin/items/{page}"}) public String itemManage(ItemSearchDto itemSearchDto, @PathVariable("page") Optional page, Model model){ Pageable pageable = PageRequest.of(page.isPresent() ? page.get() : 0, 5); Page items = itemService.getAdminItemPage(itemSearchDto, pageable); model.addAttribute("items", items); model.addAttribute("itemSearchDto", ite..

ItemRepositoryCustom 이 부분인데 //리포지토리 특이한 상속!!! -- 궁금... // 형제쪽에 드러나 있는 애가 있고 숨겨진 애가 있다. // 형제끼리는 원래 형변환이 되지 않는다. (Impl이라서 가능) @Transactional(readOnly = true) public Page getAdminItemPage(ItemSearchDto itemSearchDto, Pageable pageable) { return itemRepository.getAdminItemPage(itemSearchDto, pageable); } // 원래 itemRepository.getAdminItemPage는 죽어야 하는데, 다른 자식이 구현하고 있으므로 사용 가능. // 스프링이 해주는 특이한 형태. /* ..

ItemController 추가된 부분 @GetMapping(value = "/admin/item/{itemId}") public String itemDtl(@PathVariable("itemId")Long itemId, Model model) { try { ItemFormDto itemFormDto = itemService.getItemDtl(itemId); model.addAttribute("itemFormDto", itemFormDto); } catch (EntityNotFoundException e) { model.addAttribute("errorMessage", "존재하지 않는 상품입니다."); model.addAttribute("itemFormDto", new ItemFormDto()); r..

ItemController @Controller public class ItemController { @GetMapping(value = "/admin/item/new") public String itemForm(Model model) { model.addAttribute("itemFormDto", new ItemFormDto()); return "/item/itemForm"; } } 복습하자면 Model은 MVC 패턴에서의 Model을 의미하는 게 맞고, 컨트롤러에서 뷰에 데이터를 전달할 때 Model에 담아서 전달함. Model은 데이터를 뷰로 전달하기 위해 사용되는 객체. 컨트롤러에서 데이터를 추가하고, 이를 뷰에 전달할 수 있다. Map과 똑같다. ItemFormDto @Getter @Setter..
언제 저장했는지, 언제 변경했는지 / 누가 저장했는지, 누가 변경했는지 에 대한 정보는 엔티티 관계없이 모두가 들고 있다. 그런데 어떤 엔티티는 등록자/수정자가 의미 없을 수도 있고, 어떤 엔티티는 등록/수정시간이 의미 없을 수도 있다. 이런 걸 구분하기 위해서... 지금 교재에는 BaseTime entity가 부모로 있는 걸 봐서 등록자/수정자가 관심 없는 상태이다. 둘 다 궁금한 상태이면 BaseEntity를 붙여주면 된다. 감시의 힘은? 만약 없다면 이것들을 어떻게 처리해야 하는가. - 쿼리 날릴 때 이 정보들을 알려주던가(할때마다 일일이 로직 추가) - 등록자 수정자는 항상 들고와야하는데? 어디서? 업데이트하는 값이기 때문에((주로 사용자로부터 옴) 사용자로부터 연결된 컨트롤러에서 온다. 장시간 ..
지연로딩을 기본값으로 설정하라는 대전제 어노테이션 @OneToOne, @ManyToOne 처럼 뒤가 One으로 끝나면 default가 EAGER (즉시) @OneToMany, @ManyToMany 처럼 뒤가 Many로 끝나면 default가 LAZY (지연) orphanRemoval 고아 객체 제거 @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) private List orderItems = new ArrayList(); Order가 여러 개의 OrderItem 을 들고 있는데, 지금 이 관계에서는 OrderItem이 자식에 가깝다. 그런데 만약 Order가 삭제가 되..

스프링 부트 쇼핑몰 프로젝트 with JPA 카트와 멤버 -> 상식에 기대어 One To One 관계 외래키 => 상대방의 키를 내가 들고 있다 = 외래키를 가지고 있다. => 상대방의 키가 내게 외래키 컨벤션은 정해져 있지만, 명시적으로 적어놓으면 좋다. 데이터베이스 세상에서는 key 값만 외래키로 들고있다면, 객체세상에서는 엔티티 자체를 가진다. (JPA의 관여) @Entity @Getter @Setter @Table(name = "cart_item") public class CartItem { @Id @GeneratedValue @Column(name = "cart_item_id") private Long id; @ManyToOne @JoinColumn(name = "cart_id") private..
@Enumerated(EnumType.STRING) -> Enum을 처리하기 위한 어노테이션 그런데 기본값은 EnumType.ORDINAL => 0, 1로 이루어진 숫자. 이러면 값이 중간에 삭제되거나 순서가 바뀌거나 하면 사고난다. 왜 쿼리Dsl을 쓰는가? 쿼리dsl을 쓰면 쿼리문 중간에 오타 발생률이 현저히 낮아진다. 컴파일 시점에 에러를 잡아내기 때문에 그렇다. JPQL이라면 런타임에서나 발견될만한 에러를 컴파일 단위에서 끌어내려서 먼저 발견. ---------------------- 컴파일 에러와 런타임 에러는 모두 프로그램 개발과 실행 과정에서 발생할 수 있는 문제입니다. 그러나 둘은 서로 다른 종류의 오류이며, 발생하는 시점과 원인도 다릅니다. 컴파일 에러는 소스 코드를 컴파일하는 과정에서 발..