Search
Duplicate

웹 계층 개발

홈 화면과 레이아웃

tymeleaf를 사용하였다.
header,bodyHeader,footer를 thymeleaf의 replace기능을 이용하여 layout을 적용해줬다.
bootstrap과 jumbotron-narrow.css를 사용한다(jumbotron-narrow.css는 제공하는 소스를 사용)

home.html

Code Content

fragment::header

Code Content

fragment::bodyHeader

Code Content

fragment::footer

Code Content

jumbotron-narrow.css

Code Content

회원 등록

MemberController:: create

Code Content

members::createMemberForm

Code Content

Tips

BindingResult
→ Controller Parameter가 Valid체크가 실패했을경우 bindingResult.hasErrors()를 통해 에러를 담아서 되돌아갈 수 있다.
→ 이 때 form객체도 작성되있던 내용들이 같이 되돌아가서 html페이지에서는 이전 작성내용이 저장될 수 있다.
th:object="${memberForm}" / th:field="*{name}"
→ memberForm Object를 선언해준 태그안에서 th:field를 통해 memberForm의 attribute를 꺼내서 바로 사용할 수 있다.

회원 목록 조회

members::memberList

Code Content

MemberController::list

Code Content

Tips

thymeleaf에서 ? 을 사용하면 null을 무시한다 (ex: ${member.address?.city})
API를 만들 때는 절대로 엔티티를 반환해서는 안된다. (ex: Member일 경우 password 노출)
→ 템플릿엔진에서는 선택적으로 사용해도 된다(server side에서 돌기 때문에)
→ 그래도 DTO나 화면에 맞는 DataObject로 transform 해서 반환하는 것이 좋다.

상품 등록

items::createItemForm

Code Content

Controller::ItemController

Code Content

DTO::BookForm

Code Content

상품 목록

items::itemList

Code Content

ItemController::list

Code Content

상품 수정

items::updateItemForm

Code Content

ItemController::updateItemForm

Code Content

ItemController::updateItem

Code Content

변경 감지와 병합(merge)(Important!!)

준영속 엔티티란?

→영속성 컨텐츠가 더는 관리하지 않는 엔티티이다.
@PostMapping("/items/{itemId}/edit") public String updateItem(@ModelAttribute("form") BookForm form, @PathVariable String itemId){ Book book = new Book(); book.setId(form.getId()); book.setName(form.getName()); book.setPrice(form.getPrice()); book.setStockQuantity(form.getStockQuantity()); book.setAuthor(form.getAuthor()); book.setIsbn(form.getIsbn()); itemService.saveItem(book); return "redirect:/items"; }
Java
복사
위 코드를 보자. 위의 새로 생성 된 book객체는 new를 통해 새로 생성된 객체이고, 아직 영속성 컨텍스트에는 등록되지 않았지만, 식별자를 가지고 있다.
이처럼 임의로 엔티티 객체를 만들어 내도 식별자를 가지고 있으면 준영속 엔티티라 한다.

준영속 엔티티를 수정하는 방법

1.
변경 감지 기능
2.
병합(merge)기능

변경 감지 기능 사용

Code Content

병합 기능 사용

Code Content

병합 기능 로직

1.
merge() 실행
2.
파라미터로 넘어온 준영속 엔티티의 식별자 값으로 1차 캐시에서 엔티티 조회
→ 만약 1차 캐시에 엔티티가 없을 경우 DB에서 엔티티 조회 후, 1차 캐시에 저장.
3.
조회한 영속 엔티티에 member엔티티의 값을 채워 넣는다. (member의 모든 값을 mergeMember에 setting해준다.)
4.
영속 상태인 mergeMember를 반환한다.
5.
트랜잭션 커밋 시점에 해당 mergeMember로 update sql을 수행한다.
주의점: 병합(merge)의 경우 모든 값을 변경해주기 때문에 의도하지 않은 변경도 있을수가 있다. (Ex: 따로 변경을 원하지 않아 null인 값들마저 모두 변경되버릴 수 있다.)

정리

1.
엔티티를 변경할 때는 항상 변경 감지를 사용하도록 하자.
2.
컨트롤러에서 어설프게 엔티티를 생성하지 마세요.
3.
트랜잭션이 있는 서비스 계층에 식별자와 변경할 데이터를 명확하게 전달하자.(파라미터 or DTO)
4.
트랜잭션 커밋 시점에 변경감지가 실행됩니다.

상품 주문

order::orderForm

Code Content

OrderController

Code Content

Tips

커맨드성 로직들은 Controller에서는 식별자만 넘겨주고, Service단에서 핵심 로직들을 수행하는게 좋다. 트랜잭션 내부에서 관리되고 엔티티들이 영속상태인데, Controller단에서 엔티티를 파라미터로 받으면, 해당 엔티티는 준영속 상태가 되기때문에 부작용(sideEffect)를 유도할 수 있다.

주문 목록 검색, 취소

OrderController::orderList+cancelOrder

Code Content

order::orderList

CodeContent