본문 바로가기
Spring/스프링 기본 원리

[Spring-data-mongo] Mongo Entity 목록 식별하기

by Taler 2022. 10. 8.

Jpa를 사용하는 대부분의 RDB들에 매핑되는 Entity의 정보를 식별하기 쉽다. 단지 EntityManager의 MetaModel을 호출하고, 해당 모델에서 Entity들의 정보를 가져오기만 하면 된다.

 

Jpa Entity 가져오기. Entiti Annotation이 달려있는 모든 Class의 정보를 가져온다.

반면 MongoDB에 매핑되는, @Document 어노테이션이 붙은 Entity들의 정보를 식별하기 위해서는 MongoMappingContext를 사용해 getPersistentEntities() 메소드를 사용함으로써 MongoPersistentEntity들의 정보를 가져올 수 있다.

 

...

    private final MongoMappingContext mmc;
    
    ...
    
    	Collection<MongoPersistentEntity<?>> mongoEntityList = mmc.getPersistentEntities();
        
        // or
        
    	Set<MongoPersistentEntity<?>> mongoEntityList = new HashSet<>(mmc.getPersistentEntities());
        
   	...
    
...

 

 

그렇다면, 해당 MappingContext에는 어떤 Entity들이 매핑될 수 있고, 어떤 정보들을 담고 있는지도 알아보자.

 

 

상세 정보

 


위에서 언급했던 Jpa EntityManager에 의해서 식별되는 클래스는 다음과 같다.

 

...

@Getter
@NoArgsConstructor
@Table(name = "Menu", schema = "public")
@Entity
public class MigrationMenuExample extends BaseMigrationEntity {
    @Id
    private Long menuId;
    

    private String title;

    private Long turn;

    private Long userId;

    public MigrationMenuExample(Date regDate, Date modDate, Long menuId, String title, Long turn, Long userId) {
        super(regDate, modDate);
        this.menuId = menuId;
        this.title = title;
        this.turn = turn;
        this.userId = userId;
    }
}

...

 

위와 같이 @Entity 어노테이션이 추가된 Class들은 모두 Entity로 인식되고, 해당 Entity들에 대한 정보 (Type이나 이름, 가진 속성들까지) 모두 가져올 수 있다. EntityType이라는 객체는 IdentifiableType의 확장이며, 이것은 ManagedType, Type의 확장이다. 이렇게 각각의 Type들은 해당 Type이 포함하고 있는 모든 속성들을 포함한다.

 

반면 Mongo에서는 달랐다. MongoEntity는 @Document 어노테이션을 추가함으로써 식별된다.

 

@NoArgsConstructor
@Getter
@Document(collection = "User")
public class LegacyUserExample implements BaseLegacyEntity {

    @Id
    private String id;

    @Indexed
    private Long userId;

    private String email;

    private String name;

    private String type;

    private Date regDate;

    private int coin;

    @Override
    public MigrationUserExample convert() {
        return new MigrationUserExample(userId, email, name, type, coin, regDate);
    }

    public LegacyUserExample(String id, Long userId, String email, String name, String type, Date regDate, int coin) {
        this.id = id;
        this.userId = userId;
        this.email = email;
        this.name = name;
        this.type = type;
        this.regDate = regDate;
        this.coin = coin;
    }
}

 

이렇게 식별된 MongoEntity들은 당연히 EntityManager에 의해서 관리되지 않았다. (EntityManager는 @Entity 어노테이션이 붙어있는 객체들을 관리한다.) 그렇다고 MongoEntity에 @Entity 어노테이션을 추가해 EntityManager로 식별하고자 하면, Jpa와 연결되어있는 DB에 매핑되어 테이블들이 생겨난다.

 

해당 DB는 Migration DB이다.

 

아무렇지 않게 생각할 수도 있지만, 이런 불필요한 테이블들이 운영 DB에 남는다는 것은 상당히 불쾌한 일이다. 그래서 MongoDB에만 Mapping될 수 있으며 이들을 관리할 방법이 있어야 했다. (당연히 소스는 없었다... 이젠 당연해지고 있다..)

 

Spring-data-mongo 패키지를 뒤적거리다가 겨우 찾아낸 것이, Mongo Entity들의 정보는 MongoPersistentEntity라는 객체로 저장된다는 점이었고, 해당 객체들은 MongoMappingContext에 의해 관리된다는 점이었다.

 

MongoPersistentEntity객체들은 Jpa의 EntityType과 마찬가지로 Entity에 대한 다양한 메타정보를 포함하고 있었으며, 메소드 이름도 크게 다르지 않았다. 필자가 사용했던 메소드 중 다른게 있다면 EntityType의 getName은 간단히 Entity의 이름만 가져왔다면, MongoPersistentEntity의 getName 메소드는 패키지를 포함한 Entity의 이름을 가져온다는 것이다. 그래서 함께 사용하고자 한다면 아래와 같은 전처리 과정이 요구됐다.

 

MongoEntity에서는 packageName의 길이 이후부터 Name을 잘라서 가져온다.

 

이런 작은 차이들이 있기 때문에 MongoPersistentEntity와 EntityType을 병행해서 사용한다면 꼭 어떤 값들이 나오는 확인하고 사용하도록 하자.

 

 

결론


MongoDB에 매핑되는 @Document가 추가된 Entity들의 정보는 MongoMappingContext의 getPersistentEntities() 메소드를 통해 가져올 수 있고, Jpa에 의해서 RDB에 매핑되는 @Entity가 추가된 Entity들의 정보는 EntityManager.getMetamodel().getEntities() 메소드를 사용해 가져올 수 있다.

 

또한 유독 Spring-data-mongo에 대한 소스가 없었다. 심지어 공식문서에서도 Entity 정보를 가져오는 부분에 대해서는 설명하고 넘어가질 않았다. 해당 공식 문서에는 모든 Entity들에 대해 index를 생성하는 방법으로 getPersistentEntities 메소드가 등장할 뿐 어디에도 해당 메소드에 대한 말은 없었다.

 

spring mongo의 길은 험난하기만 하다..

댓글