我们知道,如果你用Java的Sping Data 框架映射Pojo为MongoDB数据时,数据库中会自动给你添加一个_class字段,那这个字段是干嘛用的呢?我们可以不可以不要这个字段呢?
直接上结论:答案其实很简答,这个字段就是用来映射Pojo的,更具体的说,是为了方便处理Pojo中存在继承的情况,增加系统的扩展性的,接下来上例子:
_class字段帮助映射子类
为了方便演示,这里用Spring Data 给我们提供的mongoTemplate来操作。有关mongoDB和Spring Data的环境我就不贴了,直接上测试代码:
拥有继承关系的实体类
@Document是把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的文档。
父类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;
}
}
子类 Student
@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实现
@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条数据:
查询小张,得到的类是Student类吗?
可以看到,最终展示的是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类。