🔗 코드 확인하기
view
리소스 등록🔗 부트스트랩
resources/static
하위에 css
, js
추가resources/static/css/jumbotron-narrow.css
추가jumbotron-narrow.css
는 강사님 코드)🔗 코드 확인하기
→ 회원 가입에 성공하면 홈 화면으로 리다이렉트된다.
MemberForm.java
@NotEmpty(message = "회원 이름은 필수 입니다")
private String name;
→ 이렇게 @NotEmpty
어노테이션이 달려있는 필드는 필수값으로 설정한다.
📌 폼 객체 vs 엔티티 직접 사용
실무에서 엔티티는 핵심 비즈니스 로직만 가지고 있고, 화면을 위한 로직은 없어야 한다.
화면이나 API에 맞는 폼 객체나 DTO를 사용해서 화면이나 API 요구사항을 처리하고, 엔티티는 최대한 순수하게 유지하자!
/items/new
를 POST 방식으로 요청redirect:items
)으로 리다이렉트/items/{itemId}/edit
URL을 GET 방식으로 요청한다.updateItemForm()
메서드를 실행한다.itemService.findOne(itemId)
를 호출해서 수정할 상품을 조회한다.items/updateItemForm
)에 전달한다.Submit
버튼을 클릭한다./items/{itemId}/edit
URL을 POST 방식으로 요청하고 updateItem()
메서드를 실행한다.item
엔티티 인스턴스는 현재 준영속 상태!
수정 완료!
merge
) ] ⭐💡 준영속 엔티티
: 영속성 컨텍스트가 더는 관리하지 않는 엔티티
@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";
}
위의 코드에서 itemService.saveItem(book)
에서 수정을 시도하는 Book
객체를 준영속 엔티티라고 한다.
Book
객체는 이미 DB에 한 번 저장되어서 식별자가 존재한다.📌 준영속 엔티티를 수정하는 2가지 방법
- 변경 감지 기능 사용
- 병합(
merge
) 사용
영속성 컨텍스트에서 엔티티를 다시 조회한 후에 데이터를 수정하는 방법
@Transactional
public void updateItem(Long itemId, Book param) {
Item findItem = itemRepository.findOne(itemId);
findItem.setPrice(param.getPrice());
findItem.setName(param.getName());
findItem.setStockQuantity(param.getStockQuantity());
}
트랜잭션 안에서 준영속 엔티티인 param
을 인자로 받아서 조회하고, 변경할 값을 선택한다.
→ 트랜잭션 커밋 시점에 변경 감지(Dirty Checking
)가 동작해서 데이터베이스에서
UPDATE SQL
실행
이렇게 변경을 감지해서 업데이트하는 것을 변경 감지라고 한다.
준영속 상태의 엔티티를 영속 상태로 변경할 때 사용하는 기능
@Transactional
void update(Item itemParam) {
Item mergeItem = em.merge(item);
}
merge()
를 실행한다.mergeMember
)에 member
엔티티의 값을 채워 넣는다. member
엔티티의 모든 값을 mergeMember
에 밀어 넣는다.mergeMember
의 회원1
→ 회원명변경
)mergeMember
를 반환한다.📌 병합시 동작 방식 정리
- 준영속 엔티티의 식별자 값으로 영속 엔티티를 조회한다.
- 영속 엔티티의 값을 준영속 엔티티의 값으로 모두 교체한다. (병합한다.)
- 트랜잭션 커밋 시점에 변경 감지 기능이 동작해서 데이터베이스에
UPDATE SQL
이 실행된다.
🚫 주의!
- 변경 감지 기능은 원하는 속성만 선택해서 변경할 수 있지만,
병합은 모든 속성이 변경된다.- 병합은 모든 필드를 교체하기 때문에 값이 없으면
null
로 업데이트 할 위험도 있다.
결론 ❗ 엔티티를 변경할 때는 항상 변경 감지를 사용하자!
- 컨트롤러에서 어설프게 엔티티를 생성하지 말자.
- 트랜잭션이 있는 서비스 계층에 식별자(
id
)와 변경할 데이터를 명확하게 전달하자. (파라미터 ordto
)- 트랜잭션이 있는 서비스 계층에서 영속 상태의 엔티티를 조회하고, 엔티티의 데이터를 직접 변경하자.
- 트랜잭션 커밋 시점에 변경 감지가 실행된다.
🔗 코드 확인하기
🔗 코드 확인하기
/order
를 GET 방식으로 호출한다.OrderController
의 createForm()
메서드를 호출하고,model
객체에 주문한 고객 정보와 상품 정보를 담아서 뷰에 넘겨준다.Submit
버튼을 누르면 /order
를 POST 방식으로 호출한다.OrderController
의 order()
메서드를 호출하고,memberId
), 주문할 상품 식별자(itemId
), 수량(count
) 정보를 받아서 주문 서비스에 주문을 요청한다./orders
로 리다이렉트한다.🔗 코드 확인하기