public class MemberForm {
@NotEmpty(message = "ํ์ ์ด๋ฆ์ ํ์ ์
๋๋ค")
private String name;
private String city;
private String street;
private String zipcode;
}
ํผ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํด์ ํ๋ฉด ๊ณ์ธต๊ณผ ์๋น์ค ๊ณ์ธต์ ๋ช ํํ๊ฒ ๋ถ๋ฆฌํ๋ค.
@NotEmpty | Null, ๋น ๋ฌธ์์ด ๋ถ๊ฐ |
@PostMapping("/members/new")
public String create(@Valid MemberForm form , BindingResult result) {
if (result.hasErrors()){
return "members/createMemberForm";
}
@Valid ํน์ง
์ ํจ์ฑ๊ฒ์ฌ , ์๋ชป๋ ํ์ ์ ๋ ฅ๊ฐ์ ํ์ธํ๊ธฐ์ํ ๊ธฐ๋ฅ
์ฌ์ฉํ๊ธฐ ์ํด์๋ build.gradleํ์ผ -> dependencies ํญ๋ชฉ ->
org.springframework.boot:spring-boot-starter-validation ์ด ์ถ๊ฐ๋์ด ์์ด์ผ ํ๋ค.
Annotaion์ ์ฝ์กฐ๊ฑด
@NotNull | Null ๋ถ๊ฐ |
@Null | Null๋ง ์ ๋ ฅ ๊ฐ๋ฅ |
@NotEmpty | Null, ๋น ๋ฌธ์์ด ๋ถ๊ฐ |
@NotBlank | Null, ๋น ๋ฌธ์์ด, ์คํ์ด์ค๋ง ์๋ ๋ฌธ์์ด ๋ถ๊ฐ |
@Size(min=,max=) | ๋ฌธ์์ด, ๋ฐฐ์ด๋ฑ์ ํฌ๊ธฐ๊ฐ ๋ง์กฑํ๋๊ฐ? |
@Pattern(regexp =) | ์ ๊ท์์ ๋ง์กฑํ๋๊ฐ? |
@Max(์ซ์) | ์ง์ ๊ฐ ์ดํ์ธ๊ฐ? |
@Min(์ซ์) | ์ง์ ๊ฐ ์ด์์ธ๊ฐ |
@Future | ํ์ฌ ๋ณด๋ค ๋ฏธ๋์ธ๊ฐ? |
@Past | ํ์ฌ ๋ณด๋ค ๊ณผ๊ฑฐ์ธ๊ฐ? |
@Positive | ์์๋ง ๊ฐ๋ฅ |
@PositiveOrZero | ์์์ 0๋ง ๊ฐ๋ฅ |
@Negative | ์์๋ง ๊ฐ๋ฅ |
@NegativeOrZero | ์์์ 0๋ง ๊ฐ๋ฅ |
์ด๋ฉ์ผ ํ์๋ง ๊ฐ๋ฅ | |
@Digits(integer=, fraction = ) | ๋์ ์๊ฐ ์ง์ ๋ ์ ์์ ์์ ์๋ฆฌ ์ ๋ณด๋ค ์์๊ฐ? |
@DecimalMax(value=) | ์ง์ ๋ ๊ฐ(์ค์) ์ดํ์ธ๊ฐ? |
@DecimalMin(value=) | ์ง์ ๋ ๊ฐ(์ค์) ์ด์์ธ๊ฐ? |
@AssertFalse | false ์ธ๊ฐ? |
@AssertTrue | true ์ธ๊ฐ? |
BindingResult
BindingResult๋ ๊ฒ์ฆ์ค๋ฅ๋ฅผ ๋ณด๊ดํ๋ ๊ฐ์ฒด๋ค.
@GetMapping("/members/new")
public String createForm(Model model) {
model.addAttribute("memberForm",new MemberForm());
return "members/createMemberForm";
}
GET ์์ฒญ์ ๋น์ด์๋ MemberForm ๊ฐ์ฒด๋ฅผ ๋ชจ๋ธ์ ๋ด์์ ๋ทฐ(ํ ํ๋ฆฟ)์ ์ ๋ฌ
@PostMapping("/members/new")
public String create(@Valid MemberForm form , BindingResult result) {
ํด๋ผ์ด์ธํธ๊ฐ ํผ์ ์์ฑํ ํ๋๋ค์ Submit ํ ๋ POST ์์ฒญ๋์ด
ํ ํ๋ฆฟ์์ ๊ฐ ํ๋์ ๊ฐ๋ค์
์ปจํธ๋กค๋ฌ์์ ๋๊ฒจ์ค ๋ชจ๋ธ์ form ๊ฐ์ฒด์ set ํ๋ค
Address address = new Address(form.getCity(), form.getStreet(), form.getZipcode());
Member member = new Member();
member.setName(form.getName());
member.setAddress(address);
memberService.join(member);
form ๊ฐ์ฒด๋ ์ด์ ๊ฐ์ด ์ค์ ๋์์ผ๋
Member ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ด member ์ ํ๋๋ค์
form ๊ฐ์ฒด์์ ๊ฐ์ ธ์์ set ํ๊ณ join(ํ์๊ฐ์ )์ ์๋ฃํ๋ค .
์ง๊ธ์ ์๋น์ค๊ฐ ์์์ ํผ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๋ฒ๊ฑฐ๋ฌ์ด ์ผ์ธ๋ฏ ํ๋ฐ
๋ ๋ณต์กํด์ง๋ฉด ์ํฐํฐ๋ฅผ ์ ์ง๋ณด์ํ๊ธฐ ์ด๋ ค์์ง๊ธฐ ๋๋ฌธ์
์ํฐํฐ๋ ํ๋ฉด์ ์ํ ๋ก์ง์ ์์ด์ผ ํ๋ค.
<td th:text="${member.address?.city}"></td>
- ํ์๋ฆฌํ์์ ?๋ฅผ ์ฌ์ฉํ๋ฉด null ์ ๋ฌด์ํ๋ค.
๋ณ๊ฒฝ ๊ฐ์ง์ ๋ณํฉ(merge)
์ค์์ ์ํฐํฐ
์์์ฑ ์ปจํ
์คํธ๊ฐ ๋๋ ๊ด๋ฆฌํ์ง ์๋ ์ํฐํฐ๋ฅผ ๋งํ๋ค.
์ค์์ ์ํฐํฐ๋ ์์ ์ํ๋ก ๊ด๋ฆฌ๋๋ค๊ฐ ์ดํ ๊ด๋ฆฌ๋์ง ์๋ ์ํ๋ฅผ ๋งํฉ๋๋ค.
์๋ฅผ ๋ค์ด์ ์ํฐํฐ ๊ฐ์ฒด๋ ์ด์์๋๋ฐ, ์์์ฑ ์ปจํ ์คํธ๊ฐ ์ข ๋ฃ๋๋ฉด์,
์์์ฑ ์ปจํ ์คํธ๊ฐ ๋๋ ์ด ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ๊ด๋ฆฌํ์ง ๋ชปํ๋ ์ํ์ธ ๊ฒ์ด์ง์.
์ด ๊ฒฝ์ฐ ๋ณดํต ์ํฐํฐ ๊ฐ์ฒด๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ด๋ฏธ ์ ์ฅ์ด ๋์ด ์์ต๋๋ค.
๋ค๋ง ๊ฐ์ฒด๊ฐ ์์์ฑ ์ปจํ ์คํธ์ ๊ด๋ฆฌ๋ฅผ ์ ํ ๋ฐ์ง ๋ชปํ๋ ์ํ์ธ ๊ฒ์ด์ง์.
๊ฒฐ๊ตญ ์ค์์์ ๊ธฐ์ค์ ๊ณผ๊ฑฐ์ ํด๋น ๊ฐ์ฒด๊ฐ ์์ ์ํ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ๋๊ณ ๊ด๋ฆฌ๋ ์ ์ด ์๋๊ฐ๋ฅผ ๊ธฐ์ค
์ด๋ฏธ ์์์ฑ ์ปจํ ์คํธ์ ๊ด๋ฆฌ๋๋ ๊ฐ์ฒด๋ฅผ ๊ทธ๋๋ก ๋ง๋ค์ด๋ธ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ค์์์ด๋ผ ํ ์ ์์ต๋๋ค.
@PostMapping("items/{itemId}/edit")
public String updateItem(@ModelAttribute("form") BookForm form) {
Book book = new Book();
book.setId(form.getId());
itemService.saveItem(book);
(์ฌ๊ธฐ์๋ itemService.saveItem(book) ์์ ์์ ์ ์๋ํ๋ Book ๊ฐ์ฒด๋ค.
Book ๊ฐ์ฒด๋ ์ด๋ฏธ DB ์ ํ๋ฒ ์ ์ฅ๋์ด์ ์๋ณ์๊ฐ ์กด์ฌํ๋ค.
์ด๋ ๊ฒ ์์๋ก ๋ง๋ค์ด๋ธ ์ํฐํฐ๋ ๊ธฐ์กด ์๋ณ์๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฉด ์ค์์ ์ํฐํฐ๋ก ๋ณผ ์ ์๋ค.)
์์์ฑ ์ปจํ ์คํธ์์ ์ํฐํฐ๋ฅผ ๋ค์ ์กฐํํ ํ์ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ ๋ฐฉ๋ฒ
@Transactional
public void updateItem(Item itemParam) { //itemParam: ํ๋ฆฌ๋ฏธํฐ๋ก ๋์ด์จ ์ค์์ ์ํ์ ์ํฐํฐ
Item findItem = em.find(Item.class, itemParam.getId()); //๊ฐ์ ์ํฐํฐ๋ฅผ ์กฐํํ๋ค.
findItem.setPrice(itemParam.getPrice()); //๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ค.
}
ํธ๋์ญ์ ์์์ ์ํฐํฐ๋ฅผ ๋ค์ ์กฐํ, ๋ณ๊ฒฝํ ๊ฐ ์ ํ ->
ํธ๋์ญ์ ์ปค๋ฐ ์์ ์ ๋ณ๊ฒฝ ๊ฐ์ง(Dirty Checking)๊ฐ ๋์ํด์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ UPDATE SQL ์คํ
ํธ๋์ญ์ ์ด ์๋ ์๋น์ค ๊ณ์ธต์์ ์์ ์ํ์ ์ํฐํฐ๋ฅผ ์กฐํํ๊ณ ,
์ํฐํฐ์ ๋ฐ์ดํฐ๋ฅผ ์ง์ ๋ณ๊ฒฝํ์ธ์. ํธ๋์ญ์ ์ปค๋ฐ ์์ ์ ๋ณ๊ฒฝ ๊ฐ์ง๊ฐ ์คํ๋ฉ๋๋ค.