[MongoDB / SpringBoot ] 엔티티 간 연결설정 , ObjectId

Glen(OH TaekJoo)·2023년 11월 20일
0

Study

목록 보기
48/53
post-thumbnail

MongoDB 엔티티간 연결방법

CRUD 공부를 마치며 이번에는 엔티티 간 연결관계를 공부하며 코드를 추가 해보았다.

기존 JPA 에서는 @OneToOne, @OneToMany, @ManyToOne 어노테이션으로 1:1, 1:n , n:1 관계를 지정해주었다.

MongoDB 를 사용했을 때에는 위 어노테이션이 아닌 @DBRef 어노테이션을 붙인 후 사용했다.

  • 1:n 일 경우

-부모쪽에

@DBRef
private List<자식클래스> 변수명; 

-자식쪽에

@DBRef
private 단일클래스명 변수명; 
  • 1:1 일 경우

-두쪽 모두

@DBRef
private 단일클래스명 변수명;

tip.

@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에서 생성한다.

Controller

@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 에 저장할 값을 받는다.

받아온 두 값을 서비스로 넘겨준다.

Service

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 와 겹쳐서 생성이 안되는 것 같다.

  • 생각한 해결방안
  1. 해당 데이터 삭제 시 Document객체 자체를 삭제하는 것이 아닌 필드 안에 값만 삭제한다.
  2. 수동으로 increment 를 걸어놓은 메서드에 list.size 가 아닌 가장 마지막 객체의 id 값을 가져와 해당 값에서 추가를 한다.
  3. 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 이런 식으로 설정을 해야겠다.

profile
병아리 개발자 의 우당탕탕 성장기

0개의 댓글