Many To One 관계를 폼을 통해서 세팅하는 방법 고민 중.
- Many 쪽의 객체를 생성할 때 반드시 One 쪽의 객체를 세팅해줘야 함.
1. Many To One 관계가 단방향일 경우.
- Many 쪽 객체가 One 쪽의 객체를 알고 있는 경우. 테이블에서도 실제 Many쪽의 릴레이션에 One쪽의 id를 가지고 있는 컬럼을 가지고 있다.
1-1. Many쪽 객체를 생성하는 페이지에서 해당 객체가 어디에 속할 지 알고 있는 경우.
- 예를 들어, 특정 게시판에서 글하나를 추가하는 경우 해당 글은 이미 자기가 어디에 속해야 할 지 알고 있다.
1-2. Many쪽 객체를 생성하는 페이지에서 해당 객체가 어디에 속할 지 모르고 있는 경우.
- 예를 들어, 티스토리 블로그처럼 글을 작성하는 시점에 해당 글이 포함될 카테고리를 선택할 수 있다.
2. Many To One 관계가 양방향일 경우.
- 위에서 언급한 관계를 설정한 뒤에 추가적으로 One 쪽의 객체에서 자기가 가지고 있는 모든 Many 쪽의 객체들을 알고 있어야 한다.
2-1. Many쪽 객체를 생성하는 페이지에서 해당 객체가 어디에 속할 지 알고 있는 경우.
2-2. Many쪽 객체를 생성하는 페이지에서 해당 객체가 어디에 속할 지 모르고 있는 경우.
폼에서 그럼 어떻게 세팅해야 할까?
1-1-1. Session에서 One 쪽 객체를 가지고 있을 경우
- 예를 들어, 현재 게시판 BoardID를 Session에서 가져와서, Post를 생성할 때, session에서 이 값을 가져와서 실제 Board 객체를 가져온 다음에 Post에 세팅하기.
int boardID = SessionUtil.getIntValue(req, "boardID"); //SessionUtil 이 있다고 치고..
Post.setBoard(boardDao.get(boardID));
1-1-2. 굳이 세션에 boardID를 담고 있어야 할까?
- 생각해보니, Sessino에 들도 다닐 필요가 없다. 게시판에서 "새글 작성하기" URL을 다음과 같이 만들면 되겠다.
addPost.do?boardID=${board.boardID}
물론 이렇게 한 다음 1-1-1. 같은 코드를 사용해서 Board 객체를 Post에 세팅한다.
1-2. Session에 모든 카테고리 목록을 들고 다닌다.
- 새 글을 작성할 때, 화면에서 카테고리 목록을 뿌려줘야 하고, 카테고리 이름 뿐만 아니라 실제 카테고리의 id도 있어야 한다. 사용자가 특정 카테고리를 선택하고 서브밋을 하면 어떻게 될까?
int categoryID = RequestUtil.getIntValue(req, "categoryID"); //RequestUtil이 있다고 치고..
Post.setBoard(categoryDao.get(categoryID);
- Session은 그럼 무거운 콜렉션을 들고 다녀야 하나? Session에서는 Category 객체 콜렉션이 아니라 Category의 ID와 Name만 들고 다니자. 하지만, 이것도 Session한테는 무리가 될 수 있을텐데..
2-1. URL을 통해서(1-1-1. 같은 방식으로) 어디에 속할지 알수 있기 때문에, 첨부터 세팅해서 폼을 채운다.(Spring의 Petclinic 예제가 사용한 방식)
- request의 속성으로 이미 새로 만들 Many 쪽의 객체가 포함 될 One 쪽 객체의 id를 알고 있기 때문에.. 폼을 채우기 전에 다음과 같이 세팅을 해서 채울 수 있음.
@RequestMapping(method = RequestMethod.GET)
public String setupForm(@RequestParam("ownerId") int ownerId, ModelMap model) {
Owner owner = this.clinic.loadOwner(ownerId);
Pet pet = new Pet();
owner.addPet(pet);
model.addAttribute("pet", pet);
return "petForm";
}
이때 위의 addPet() 메소드는 아래에 있는 Convenient Method 형태.
public void addPet(Pet pet) {
getPetsInternal().add(pet);
pet.setOwner(this);
}
2-2. 어디에 속하는지 객체인지 입력(Command 객체)을 통해서 알아낸다.
- 새로운 Many 객체를 추가할 입력 폼에서 One 쪽의 객체를 선택해야 한다.
${post.category.categoryID} 여기에 선택한 카테고리의 ID를 세팅해 주겠지. 이렇게 할 수 있으려면 new Post() 객체에 new Category()를 세팅해준 다음에 화면으로 보내줘야 돼. 안 그러면 NullPointerException이 발생할테니까...(getCategory() 호출할때..)
그럼 formBackingObject 사용해서 보내자. 그렇게 한 다음 command 객체를 받아오면 어떻게 코딩할까.
Post post = (Post)command;
CategoryDao.get(post.getCategory().getCategoryID()).addPost(post);
- 여전히 뭔가 어색하다. Post가 가지고 있는 Category는 id만 채워져있는 비어있는 카테고리이고, 이 id를 가져와서 실제 카테고리를 가져온 다음에 Post를 세팅하고 있다.
- 세션, 쿠키, 컨텍스트
Session에 무언가를 들고 다니는 것 자체가 위험할 수 있다.
- 스프링 PetClinit 예제코드