MongoDB中_class字段的做用

咱們知道,若是你用Java的Sping Data 框架映射Pojo爲MongoDB數據時,數據庫中會自動給你添加一個_class字段,那這個字段是幹嗎用的呢?咱們能夠不能夠不要這個字段呢?java

直接上結論:答案其實很簡答,這個字段就是用來映射Pojo的,更具體的說,是爲了方便處理Pojo中存在繼承的狀況,增長系統的擴展性的,接下來上例子:mongodb

_class字段幫助映射子類

爲了方便演示,這裏用Spring Data 給咱們提供的mongoTemplate來操做。有關mongoDB和Spring Data的環境我就不貼了,直接上測試代碼:數據庫

擁有繼承關係的實體類

@Document是把一個java類聲明爲mongodb的文檔,能夠經過collection參數指定這個類對應的文檔。app

父類Person框架

@Document(collection = "test")
public class Person {

  protected String name;
  protected int age;

//set/get方法
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public int getAge() {
    return age;
  }
  public void setAge(int age) {
    this.age = age;
  }
}

子類 Studentide

@Document(collection = "test")
public class Student extends Person {

  String a;
  String b;

  @Override
  public String toString() {
    return "Student{" +
        "name='" + name + '\'' +
        ", age=" + age +
        ", a='" + a + '\'' +
        ", b='" + b + '\'' +
        '}';
  }

  public String getA() {
    return this.a;
  }

  public void setA(String a) {
    this.a = a;
  }

  public String getB() {
    return this.b;
  }

  public void setB(String b) {
    this.b = b;
  }
}

Dao層

Dao接口測試

public interface PersonDao {
  void addPerson(Person person);
  Person findPersonByName(String name);
}

Dao實現this

@Repository
public class PersonDapImpl implements PersonDao {

  @Autowired
  MongoTemplate mongoTemplate;
  
  @Override
  public void addPerson(Person person) {
    mongoTemplate.save(person);
  }

  @Override
  public Person findPersonByName(String name) {
    Query query = new Query(Criteria.where("name").is(name));
    Person person = mongoTemplate.findOne(query, Person.class);
    return person;
  }
}

測試方法

public class PersonDapImplTest extends BaseTest {

  @Autowired
  PersonDao personDao;

  @Test
  public void addPerson() {
    Person person = new Person();
    person.setName("張");
    person.setAge(10);
    personDao.addPerson(person);
  }

  @Test
  public void addStudent() {
    Student student = new Student();
    student.setName("小張");
    student.setAge(12);
    student.setA("a");
    student.setB("b");
    personDao.addPerson(student);
  }

  @Test
  public void findPerson() {
    System.out.println("==============開始查找==============");

    Person person = personDao.findPersonByName("小張");

    System.out.println();
    System.out.println();
    System.out.println();

    if (person != null) {
      System.out.println(person.toString());
    }else {
      System.out.println("null");
    }
  }
}

測試結論

測試中,小張是張的子類,mongoDB中已經插入了2條數據:code

查詢小張,獲得的類是Student類嗎?blog

能夠看到,最終展現的是Student的詳細信息,說明_class能幫助咱們反序列化出子類。

那若是去掉了_class列,會是什麼樣呢?

去掉_class

去掉_class的方法須要配置一下

須要配置MappingConverter:更詳細的去掉_class的方法能夠參考其餘博文。

@Bean
  public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory,
      MongoMappingContext context, BeanFactory beanFactory, CustomConversions conversions) {
    DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
    MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
    // remove _class field
//    mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
    mappingConverter.setCustomConversions(conversions);
    return mappingConverter;
  }

去掉_class後:

再次查詢"小張"

能夠看到,mongoDB沒法幫助咱們來映射子類了。返回的數據被反序列化成了Person類。

相關文章
相關標籤/搜索