[๊ฐ์] ์ค์ ! ์คํ๋ง ๋ถํธ์ JPA ํ์ฉ1 - ์น ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ 3
์ค์ ! ์คํ๋ง ๋ถํธ์ JPA ํ์ฉ1 - ์น ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ - ์ธํ๋ฐ | ๊ฐ์
์ค๋ฌด์ ๊ฐ๊น์ด ์์ ๋ก, ์คํ๋ง ๋ถํธ์ JPA๋ฅผ ํ์ฉํด์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ค๊ณํ๊ณ ๊ฐ๋ฐํฉ๋๋ค. ์ด ๊ณผ์ ์ ํตํด ์คํ๋ง ๋ถํธ์ JPA๋ฅผ ์ค๋ฌด์์ ์ด๋ป๊ฒ ํ์ฉํด์ผ ํ๋์ง ์ดํดํ ์ ์์ต๋๋ค., ๋ณธ
www.inflearn.com
7. ์น ๊ณ์ธต ๊ฐ๋ฐ
- ํ ํ๋ฉด๊ณผ ๋ ์ด์์
//HomeController.java
@Controller
@Slf4j // log์ฌ์ฉ
public class HomeController {
@RequestMapping("/")
public String home(){
log.info("home controller");
return "home";
}
}
๋ฅผ ๋ง๋ค๊ณ home.html, footer, header, bodyheader ๋ฑ html ํ์ผ๋ค ๋ง๋ค์ด์ ๋ฃ์ด์ค
https://getbootstrap.com/docs/5.1/getting-started/download/
Download
Download Bootstrap to get the compiled CSS and JavaScript, source code, or include it with your favorite package managers like npm, RubyGems, and more.
getbootstrap.com
์ฌ๊ธฐ์
์ด๊ฑฐ ๋ฐ์์
static ํ์์ ๋ณต์ฌ ๋ถ์ฌ๋ฃ๊ธฐ ํด์ค๋ค. ์ ์ฉ ์๋๋ ๊ฒฝ์ฐ ๋น๋ ๋ค์ํ๊ธฐ
๊ทธ๋ฆฌ๊ณ ๊ฐ์ฌ๋์ด ์ฃผ์ css์ฝ๋๊น์ง ์ถ๊ฐํด์ฃผ๋ฉด ๋๋ค.
- ํ์ ๋ฑ๋ก
@NotEmpty๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ์ด ๋ฌธ๊ตฌ๋ฅผ build.gradle์ ์ถ๊ฐํด์ค์ผ ํ๋ค.
implementation 'org.springframework.boot:spring-boot-starter-validation'
//MemberForm.java
@Getter@Setter
public class MemberForm {
@NotEmpty(message = "ํ์ ์ด๋ฆ์ ํ์ ์
๋๋ค.")
private String name;
private String city;
private String street;
private String zipcode;
}
//MemberController.java
@Controller
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
@GetMapping("/members/new")
public String createForm(Model model){
model.addAttribute("memberForm", new MemberForm());
return "members/createMemberForm";
}
@PostMapping("/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:/";
}
}
Member๋ฅผ ์ฐ์ง ์๊ณ Formdata๋ฅผ ์ฐ๋ ์ด์
: Member๊ฐ ์ง์ ๋ถํด์ง๋ ๊ฒ์ ๋ฐฉ์งํ๊ณ , ์ ๋ถ ์์ ํ ์ด์ ๋ ์๊ธฐ์ ํ์ํ๊ฒ๋ง
์ํฐํฐ๊ฐ ํ๋ฉด ์ข ์ํ๊ฐ ๋๊ณ , ์ ์ง ๋ณด์๊ฐ ํ๋ค์ด์ง๋ค.
- ํ์ ๋ชฉ๋ก ์กฐํ
์ญ์ html์ ๋ณต๋ถ์ผ๋ก ๋ฃ์ด์ฃผ๊ณ
//MemberController.java
@Controller
@RequiredArgsConstructor
public class MemberController {
...
@GetMapping("/members")
public String list(Model model){
List<Member> members = memberService.findMembers();
model.addAttribute("members", members);
return "members/memberList";
}
}
- ์ํ ๋ฑ๋ก
//ItemController.java
@RequiredArgsConstructor
@Controller
public class ItemController {
private final ItemService itemService;
@GetMapping("/items/new")
public String createForm(Model model) {
model.addAttribute("form", new BookForm());
return "items/createItemForm";
}
@PostMapping(value = "/items/new")
public String create(BookForm form) {
Book book = new Book();
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:/";
}
}
์ญ์ htmlํ์ผ ์ถ๊ฐ ํ ์๋๋ค!
- ์ํ ๋ชฉ๋ก
//ItemController.java
@RequiredArgsConstructor
@Controller
public class ItemController {
...
@GetMapping(value = "/items")
public String list(Model model) {
List<Item> items = itemService.findItems();
model.addAttribute("items", items);
return "items/itemList";
}
}
- ์ํ ์์
//ItemController.java
@RequiredArgsConstructor
@Controller
public class ItemController {
...
@GetMapping(value = "/items/{itemId}/edit")
public String updateItem(@ModelAttribute("itemId") Long itemId, Model model) {
Book book = (Book) itemService.findOne(itemId);
BookForm form = new BookForm();
form.setId(book.getId());
form.setName(book.getName());
form.setPrice(book.getPrice());
form.setStockQuantity(book.getStockQuantity());
form.setAuthor(book.getAuthor());
form.setIsbn(book.getIsbn());
model.addAttribute("form", form);
return "items/updateItemForm";
}
@PostMapping(value = "/items/{itemId}/edit")
public String updateItem(@ModelAttribute("form") BookForm form) {
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";
}
}
์์ ์ ํ๋ผ๋ฏธํฐ๋ก ๋์ด์จ item ์ํฐํฐ ์ธ์คํด์ค๋ ์ค์์ ์ํ์ด๋ค. ์์์ฑ ์ปจํ ์คํธ๋ผ ํ ์ ์๊ณ ์์ ํด๋ ๋ณ๊ฒฝ๊ฐ์ง๊ฐ ๋์ํ์ง ์๋๋ค.
- ๋ณ๊ฒฝ๊ฐ์ง์ ๋ณํฉ
์ค์์ ์ํฐํฐ
์์์ฑ ์ปจํ ์คํธ๊ฐ ๊ด๋ฆฌํ์ง ์๋ ์ํฐํฐ
ex ) ์์ book ๊ฐ์ฒด, DB์ ํ๋ฒ ๊ฐ๋ค ์๊ธฐ์ ์๋ณ์๊ฐ ์กด์ฌํ๋ค
์ค์์ ์ํฐํฐ ์์ ํ๋ ๋ฒ
1) ๋ณ๊ฒฝ ๊ฐ์ง ๊ธฐ๋ฅ
@Transactional
//itemParam: ํ๋ฆฌ๋ฏธํฐ๋ก ๋์ด์จ ์ค์์ ์ํ์ ์ํฐํฐ
void update(Item itemParam) {
//๊ฐ์ ์ํฐํฐ๋ฅผ ์กฐํํ๋ค.
Item findItem = em.find(Item.class, itemParam.getId());
//๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ค.
findItem.setPrice(itemParam.getPrice());
}
ํธ๋์ญ์ ์ปค๋ฐ ์์ ์ ๋ณ๊ฒฝ ๊ฐ์ง Dirty Checking
2) ๋ณํฉ ์ฌ์ฉ
@Transactional
void update(Item itemParam) {
Item mergeItem = em.merge(item);
}
merge ๋ณด๋จ ๋ณ๊ฒฝ๊ฐ์ง. null๋ก ์ ๋ฐ์ดํธ ๋ ์ํ์ด ์์
- ์ฃผ๋ฌธ ๋ชฉ๋ก ๊ฒ์, ์ทจ์
//OrderController.java
@Controller
@RequiredArgsConstructor
public class OrderController {
private final OrderService orderService;
private final MemberService memberService;
private final ItemService itemService;
@GetMapping(value = "/order")
public String createForm(Model model) {
List<Member> members = memberService.findMembers();
List<Item> items = itemService.findItems();
model.addAttribute("members", members);
model.addAttribute("items", items);
return "order/orderForm";
}
@PostMapping(value = "/order")
public String order(@RequestParam("memberId") Long memberId,
@RequestParam("itemId") Long itemId, @RequestParam("count") int count) {
orderService.order(memberId, itemId, count);
return "redirect:/orders";
}
@GetMapping(value = "/orders")
public String orderList(@ModelAttribute("orderSearch") OrderSearch
orderSearch, Model model) {
List<Order> orders = orderService.findOrders(orderSearch);
model.addAttribute("orders", orders);
return "order/orderList";
}
@PostMapping(value = "/orders/{orderId}/cancel")
public String cancelOrder(@PathVariable("orderId") Long orderId) {
orderService.cancelOrder(orderId);
return "redirect:/orders";
}
}