본문 바로가기

springboot

(18)
[springboot] 순환 참조 해결 조회 쿼리를 한번에 날리기 위해서 이런식으로 작성했더니 public Optional findOrder(Long orderId, String loginId) { return em.createQuery("select o from Order o" + " join fetch o.orderItems" + " join fetch o.delivery" + " where o.member.loginId = :loginId" + " and o.id = :orderId", Order.class) .setParameter("loginId", loginId) .setParameter("orderId", orderId) .getResultList().stream().findAny(); } 주문 리스트가 중복으로 출력됐다. sel..
[springboot - h2] docker 적응기 처음(인줄 알았으나 두번째)으로 도커를 사용해봤다 내 프로젝트는 thymeleaf, springboot, h2 를 사용했는데 springboot, h2를 같이 한 번에 사용하려면 각 컨테이너를 만들고 docker compose를 사용해 묶어야 한다. 매번 개발 때랑 서비스 때랑 properties의 datasource url을 바꿔주기 귀찮아서 테스트용 h2 컨테이너도 하나 더 만들었다. 그럼 테스트 용 h2를 실행하고 그냥 인텔리제이에서 앱을 실행시키면 동작한다 spring과 h2 연결은 아래 블로그 글들을 참고했고 https://velog.io/@seungju0000/docker%EC%99%80-h2-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0 docker와 h2 연결하기 doc..
[springboot - thymeleaf] Form Dto : NullPointerException 마이페이지의 회원 정보를 미리 로딩하고, 수정 사항이 있으면 바로 POST 요청을 보내기 위해서 UpdateForm.class를 만들어 model Attribute에 매핑하고, form의 th:object로 매핑했다. MyPageController.class @GetMapping(value = "/myInfo") public String myInfo(@AuthenticationPrincipal LoginUserDetails member, Model model) { if(member==null) return "redirect:/members/login"; Member findMember = memberService.findUser(member.getUsername()); UpdateForm updateFo..
[springboot - thymeleaf] 쇼핑몰 장바구니 페이지 구현 장바구니 페이지에서 필요한 기능은 상품 선택, 수량 변경, 취소, 총 금액 표시이다. 처음에는 form 태그로 table 전체를 감싸고, 수량 변경, 취소 등은 th:formaction으로 바인딩했다. 선택 상품 주문도, post 요청의 body data로 보낼 생각이었다. 하지만 checkbox의 데이터를 실시간으로 바꿀 수 있는 것을 기억해내고(...) 체크 박스 부분, 수량 변경 부분을 각각 form으로 감싸서 해결했다. shoppingBag.html 장바구니 장바구니에 추가한 상품이 없습니다. # 상품명 가격 수량 합계 취소 총 금액 : 원 선택 상품 주문 전체 상품 주문 ShoppingBagController.java ... @PostMapping(value = {"/update"}) publi..
[springboot-thymeleaf] 쇼핑몰 상품 찜 기능 구현하기 있어야 하는 기능 찜하기 찜한 목록 보기 취소하기 찜은 상품 detail 화면에서 동작하고, 취소하는 방법은 상품 detail 화면과 찜한 목록 화면에서 동작해야한다. 또한 상품을 찜하기 위해서는 로그인이 된 상태여야 한다. 성능 최적화는 아직 고려하지 않았다. 도메인 설계 member 객체가 like item의 list를 갖고, like item이 item과 member의 다대다 관계를 풀어준다. UI 구현 상품 화면에서 찜 했으면 버튼 색을 칠하고, 찜하지 않았거나 로그인 상태가 아니라면 칠하지 않도록 보이게 했다. 목록도 단순하게 나열만 하고, 취소를 통해 바로 취소할 수 있도록 했다. 상품 상세 페이지 UI ItemController.java @GetMapping(value = "/detail")..
[thymeleaf] form 태그 아래 submit이 여러 개일 때 해당 화면 구성을 위해 주문하기, 장바구니, 찜 이렇게 세개의 submit button이 필요했다. 먼저, submit이 하나만 있을 때는 form 태그에 method와 action을 지정해 주고, 단순하게 button을 추가하면 된다. ... 주문하기 submit이 여러 개일 때는 각 button에 formaction을 지정해주면 된다. ... 주문하기 장바구니 찜 더보기 사실 이것 말고도 다른 고민이 있었다. 세 요청(주문하기, 장바구니, 찜) 모두 member_id, item_id가 필요했다. member_id는 Controller에서 @AuthenticationPrincipal을 통해 로그인 유저 정보를 받으면 그만이지만, form 내부에서 item과 관련된 정보는 사용하지 않았기 때문이다. 따라..
[스프링 부트 JPA 활용] 도메인 분석 설계 도메인 분석 설계 https://www.inflearn.com/course/스프링부트-JPA-활용-1/dashboard Member - Order Member과 Order는 양방향 일대다 다대일 관계이다. @JoinColumn(name="member_id")로 Order가 member의 member_id를 FK로 가진다. Member는 Order를 단순 조회용으로 사용하고 Order의 값을 바꿔야 이 연관관계에서 데이터가 바뀌며, Order를 생성할 때 Member가 필요하기 때문에 연관관계의 주인은 Order가 된다. * 보통 일대다 관계에서는 '다'에 해당하는 쪽이 주인을 가져간다. * FK에 가까운 쪽이 주인이 된다. Order - OrderItem도 비슷하다. OrderItem - Item 단방향..
[스프링 핵심 원리] @Autowired @Qualifier @Primary 조회 대상 빈이 2개 이상일 때 해결 방법이 세가지가 있다. @Autowired 필드 명 매칭 @Qualifier끼리 매칭 => 빈 이름 매칭 @Primary 사용 @Autowired 필드 명 매칭 @Autowired는 타입 매칭을 먼저 시도하고, 같은 타입의 빈이 여러개가 있으면 필드 이름, 파라미터 이름으로 추가적으로 매칭한다. @Autowired private DiscountPolicy rateDiscountPolicy 이런식으로 필드명을 정의하면 FixDiscountPolicy와 RateDiscountPolicy 중 RateDiscountPolicy를 매칭한다. @Qualifier 사용 빈 이름을 변경하는 대신 추가 구분자를 붙여주는 방법이다. @Component @Qualifier("mainDi..