MongoDB 엔티티간 연결방법
CRUD 공부를 마치며 이번에는 엔티티 간 연결관계를 공부하며 코드를 추가 해보았다.
기존 JPA 에서는 @OneToOne, @OneToMany, @ManyToOne 어노테이션으로 1:1, 1:n , n:1 관계를 지정해주었다.
MongoDB 를 사용했을 때에는 위 어노테이션이 아닌 @DBRef 어노테이션을 붙인 후 사용했다.
-부모쪽에
@DBRef
private List<자식클래스> 변수명;
-자식쪽에
@DBRef
private 단일클래스명 변수명;
-두쪽 모두
@DBRef
private 단일클래스명 변수명;
@DBRef(lazy = true)
위와 같이 설정 되어있을 경우 부모클래스가 로드 되더라도 자식클래스는 필요로 할 때만 로드된다. ('지연로딩' 설정)
실제 코드 적용
@Data
@Getter
@Setter
@Document("1234_adress")
@AllArgsConstructor
@NoArgsConstructor
public class MongoAdress {
@Id
private String id;
@DBRef
private Mongo mongo;
private String adress;
}
@DBRef 를 사용하여 n:1 관계를 설정했다.
엔티티 클래스에서 선언한 컬렉션명과 동일한 컬렌션을 db에서 생성한다.
@PostMapping("/adress/{id}")
public String CreateAdress(@PathVariable String id , @RequestParam(value = "adress")String adress){
Mongo mongo = this.mongService.getId(id);
MongoAdress mongoAdress=this.adressService.createAdress(mongo,adress);
return mongoAdress.getMongo().getId()+"번 몽고의 주소로"+mongoAdress.getAdress()+" 가 등록되었습니다";
}
PathVariable 로 기존 Mongo 엔티티 의 id 값을 받아 해당 id 값으로 Mongo 를 찾아온다.
@RequestParam 으로는 MongoAdress 의 adress 에 저장할 값을 받는다.
받아온 두 값을 서비스로 넘겨준다.
public MongoAdress createAdress(Mongo mongo, String adress){
MongoAdress mongoAdress = new MongoAdress();
mongoAdress.setId(Integer.toString(Integer.parseInt(this.adressRepo.findTopByOrderByCreatedAtDesc().get(0).getId())+1));
mongoAdress.setMongo(mongo);
mongoAdress.setAdress(adress);
this.adressRepo.insert(mongoAdress);
return mongoAdress;
}
mongoAdress 빈 객체를 만들어 받아온 mongo 와 adress값 을 넣는다.
mongoDB 는 Auto_increment 를 지원하지 않는다고하여 수동으로 id 값을 올려서 저장하는 방법으로 위와같이 작성을 했었다.
@Id 어노테이션만 생성하면 ObjectId 를 자동으로 생성해준다고 한다 --;;
사진과 같이 객체 고유ID가 들어가 있으나 고유ID보다는 단순넘버링으로 쉽게 확인하기 위해 다시 수동으로 값을 올려 저장되도록 메서드를 수정했다..
public MongoAdress createAdress(Mongo mongo, String adress){
MongoAdress mongoAdress = new MongoAdress();
mongoAdress.setId(Integer.toString(this.adressRepo.findAll().size()+1));
mongoAdress.setMongo(mongo);
mongoAdress.setAdress(adress);
this.adressRepo.insert(mongoAdress);
return mongoAdress;
}
저장된 전체목록을 list 로 가져와서 해당 리스트의 크기에 +1 을 하는 방법으로 작성했다.
추후 삭제관련하여 문제가 생기겠지만 일단 데이터 확인만 진행하고 추후 수정을 하려고 한다.
결과값 :
포스트맨으로 해당 url 로 요청을 보낸 결과 설정해뒀던 문구가 정상적으로 반환되었다.
id 값이 설정한대로 하나씩 올라가고 mongo(부모) 도 정상적으로 들어갔다.
삭제하기
추가로 수동설정했던 id 값이 데이터 하나를 삭제 후 재생성 하면 어떻게 나오는지 궁금해서
삭제도 진행해 보았다. (List 값은 )
@DeleteMapping("/adress/delete/{id}")
public String deleteAdress(@PathVariable String id){
this.adressService.delete(id);
return id+"번 adress 가 삭제되었습니다 ";
}
MongoAdress 2,5번을 삭제했다.
재등록을 하려고 하니 500 에러가 나온다..
list의 size 가 줄어 설정한 id 값이 기존에 있는 id 와 겹쳐서 생성이 안되는 것 같다.
지금 선택한 방법은 2번이다. 가장 빠르게 수정하고 다른부분은 건들지 않아도 된다는 점에서 2번을 선택했다.
id설정 메서드 수정
초기에 만들었던 지저분한 고유id 를 가진 객체를 먼저 삭제했다.
public MongoAdress createAdress(Mongo mongo, String adress){
MongoAdress mongoAdress = new MongoAdress();
mongoAdress.setId(Integer.toString(Integer.parseInt(this.adressRepo.findTopByOrderByIdDesc().getId())+1));
mongoAdress.setMongo(mongo);
mongoAdress.setAdress(adress);
this.adressRepo.insert(mongoAdress);
return mongoAdress;
}
id 값을 기준으로 가장 최근값을 가져와 해당 id의 값에서 +1 을 하였다.
하지만 다른문제가 발생했다...
id 값의 자료형이 문자형이다 보니 10번이 맨뒤로 리셋되었다. 9번이 정렬의 마지막으로 지정되다 보니 10번이 생성된 후 다음생성도 10번으로 생성되어 오류가 발생했다.
이문제는 추후 LocalDateTime 을 사용하여 생성일 기준으로 데이터를 가져와 id 를 추가하거나 objectId를 0001 0002 이런 식으로 설정을 해야겠다.