JPA 활용1 - 웹 계층 개발

기석·2022년 5월 30일
0
post-thumbnail

스프링 부트와 JPA 활용1 강의를 듣고 정리한 내용입니다.

JPA 활용1의 마지막 강의다.
MVC 기능을 주로 다룰 것 같아 배울 내용 보다는 구현이 많을거라 예상했는데 배울 것이 많았다.

폼 객체

폼 객체를 이용해서 화면 계층과 서비스 계층을 명확하게 분리한다.
엔티티로 화면 입력을 받게되면 여의치 않은 예외상황이 발생할 수 있다.

실무에서 엔티티는 핵심 비즈니스 로직만 가지고 있고, 화면을 위한 로직은 없어야 한다.

회원 등록 폼

@Getter @Setter
public class MemberForm {
 	@NotEmpty(message = "회원 이름은 필수 입니다")
 	private String name;
 	private String city;
 	private String street;
 	private String zipcode;
}

회원 등록

@Controller
@RequiredArgsConstructor
public class MemberController {
 	private final MemberService memberService;
 	
    @GetMapping(value = "/members/new")
 	public String createForm(Model model) {
 		model.addAttribute("memberForm", new MemberForm());
 		return "members/createMemberForm";
 	}
    
 	@PostMapping(value = "/members/new")
 	public String create(@Valid MemberForm form, BindingResult result) {
 		if (result.hasErrors()) {
 			return "members/createMemberForm";
 		}
 		Address address = new Address(form.getCity(), form.getStreet(),
		form.getZipcode());
 		Member member = new Member();
 		member.setName(form.getName());
 		member.setAddress(address);
 		memberService.join(member);
 		return "redirect:/";
 	}
}

변경 감지와 병합(merge)

준영속 엔티티

영속 컨텍스트가 더이상 관리하지 않는 엔티티.
정확히는 기존 DB에 대한 식별자를 가지고 있으나 영속성 컨텍스트에 등록되지 않은 엔티티를 말한다.

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

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

변경 감지 기능 사용 방법

@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티
 	Item findItem = em.find(Item.class, itemParam.getId()); //같은 엔티티를 조회한다.
 	findItem.setPrice(itemParam.getPrice()); //데이터를 수정한다.
}

영속성 컨텍스트에서 엔티티를 다시 조회한 후에 데이터를 수정한다.
=> 트랜잭션 커밋 시점에 변경 감지(Dirty Checking) 후 DB에 UPDATE SQL을 자동으로 실행한다.

병합 사용

@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티
	 Item mergeItem = em.merge(item);
}

병합은 준영속 상태의 엔티티를 영속 상태로 변경할 때 사용하는 기능이다.


변경감지 vs 병합

변경감지 기능을 사용하면 원하는 속성만 선택해 변경할 수 있지만,
병합을 사용하면 없는 속성을 포함한 모든 속성이 변경되어 null로 업데이트할 위험이 있다.
=> 엔티티를 변경할 때는 항상 변경 감지를 사용한다.

  1. 컨트롤러에서 엔티티를 생성하지 말자.
  2. 트랜잭션이 있는 서비스 계층에 식별자와 데이터를 전달하라.
  3. 트랜잭션이 있는 서비스 계층에서 영속 상태의 엔티티를 조회하고 데이터를 변경하라.
  4. 트랜잭션 커밋 시점에 변경 감지가 실행된다.

컨트롤러

@Controller
@RequiredArgsConstructor
public class ItemController {
 	private final ItemService itemService;
 	/**
 	* 상품 수정, 권장 코드
 	*/
 	@PostMapping(value = "/items/{itemId}/edit")
 	public String updateItem(@ModelAttribute("form") BookForm form) {
 		itemService.updateItem(form.getId(), form.getName(), form.getPrice());
 		return "redirect:/items";
 	}
}

서비스

package jpabook.jpashop.service;
@Service
@RequiredArgsConstructor
public class ItemService {
 	private final ItemRepository itemRepository;
 	/**
 	* 영속성 컨텍스트가 자동 변경
 	*/
 	@Transactional
 	public void updateItem(Long id, String name, int price) {
 		Item item = itemRepository.findOne(id);
 		item.setName(name);
 		item.setPrice(price);
 	}
}
profile
개바라자

0개의 댓글