添加依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.hf</groupId>
<artifactId>mongodemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mongodemo</name>
<description>spring boot mongo</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--mongodb依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
在application.properties中配置连接mongodb
#配置mongodb,用户名和账号为root:root,端口为默认端口:27017,连接的数据库为: runoob
spring.data.mongodb.uri=mongodb://root:root@localhost:27017/runoob
新建实体,用来作为保存到mongo中的数据
package com.hf.mongodemo.model;
import lombok.Data;
import lombok.ToString;
import java.io.Serializable;
/**
* @Description:
* @Date: 2019/2/15
* @Auther:
*/
@Data
@ToString
public class User implements Serializable {
private Long id;
private String userName;
private String passWord;
}
创建操作mongodb的接口:
package com.hf.mongodemo.dao;
import com.hf.mongodemo.model.User;
/**
* @Description:
* @Date: 2019/2/15
* @Auther:
*/
public interface UserDao {
void saveUser(User user);
User findUserByUserName(String userName);
void updateUser(User user);
void deleteUserById(Long id);
}
接口实现类,主要是通过MongoTemplate来实现的;
package com.hf.mongodemo.dao.impl;
import com.hf.mongodemo.dao.UserDao;
import com.hf.mongodemo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;
/**
* @Description:
* @Date: 2019/2/15
* @Auther:
*/
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private MongoTemplate mongoTemplate;
@Override
public void saveUser(User user) {
/**指定文档数据保存到集合user中去**/
mongoTemplate.save(user,"user");
System.out.println("对象保存成功了!");
}
@Override
public User findUserByUserName(String userName) {
Query query = new Query(Criteria.where("userName").is(userName));
User user = mongoTemplate.findOne(query, User.class);
System.out.println(user);
return user;
}
@Override
public void updateUser(User user) {
Query query = new Query(Criteria.where("id").is(user.getId()));
Update update = new Update().set("userName", user.getUserName()).set("passWord", user.getPassWord());
//更新查询返回结果集的第一条
mongoTemplate.updateFirst(query,update,User.class);
//更新查询返回结果集的所有
//mongoTemplate.updateMulti(query,update,User.class);
}
@Override
public void deleteUserById(Long id) {
Query query = new Query(Criteria.where("id").is(id));
mongoTemplate.remove(query,User.class);
}
}
在测试类中测试:
package com.hf.mongodemo;
import com.hf.mongodemo.dao.UserDao;
import com.hf.mongodemo.model.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class MongodemoApplicationTests {
@Test
public void contextLoads() {
}
@Autowired
private UserDao userDao;
@Test
public void testSaveUser(){
User user=new User();
user.setId(1L);
user.setUserName("小红");
user.setPassWord("hello world");
userDao.saveUser(user);
}
@Test
public void findUserByUserName(){
User user= userDao.findUserByUserName("小红");
System.out.println("user is "+user);
}
@Test
public void updateUser(){
User user=new User();
user.setId(1L);
user.setUserName("yuyuyu");
user.setPassWord("hahah");
userDao.updateUser(user);
}
@Test
public void deleteUserById(){
userDao.deleteUserById(1L);
}
}
操作之前我们先查看user集合中的数据为空:(我使用的是compass来查看的,也可以通过命令行来查看)
我们执行新增操作:
可以看到执行成功了,再次查看集合中的数据:
可以看到数据新增成功了,但是发现多了一个字段 : _class,并且值为我们的实体类的全路径,这是什么原因呢??
原因是:我们使用的是spring-data来操作mongodb的,会默认在新增对象的时候添加_class属性,目的是:当我们新增的实体类继承了其他的实体类的时候,有这个_class属性就可以转换为具体的子类,如果没有这个属性,那么在转换的时候就只会转换为他的父类.
如果需要去除这个_class属性,可以使用增加配置类/xml的方式来实现,这里之写出增加配置类的方式;
新建一个配置类,如下:
package com.hf.mongodemo.config;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.convert.CustomConversions;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
/**
* @Description:配置MappingMongoConverter,目的是去除mongo保存对象的时候,自动添加_class属性
* @Date: 2019/2/15
* @Auther:
*/
@Configuration
public class SpringMongoConfig {
@Bean
public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context, BeanFactory beanFactory) {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
try {
mappingConverter.setCustomConversions(beanFactory.getBean(CustomConversions.class));
} catch (NoSuchBeanDefinitionException ignore) {
}
// Don't save _class to mongo,将DefaultMongoTypeMapper中的typeKey设为null,去除自动添加_class属性到文档中去
mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
return mappingConverter;
}
}
删除掉之前的数据,再次新增数据,得到的结果如下:
可以看到_class属性已经没有添加到文档中去了.
下面我们针对有无_class属性的测试:
新建一个实体类: Person,该类继承User
package com.hf.mongodemo.model;
import lombok.Data;
import lombok.ToString;
import java.io.Serializable;
/**
* @Description:
* @Date: 2019/2/15
* @Auther: wm yu
*/
@Data
@ToString
public class Person extends User implements Serializable {
private String name;
private int age;
}
注释掉,去除_class的配置类,也就是注释掉:SpringMongoConfig这个类
重新修改保存的测试方法,如下:
@Test
public void testSaveUser(){
User user=new User();
user.setId(1L);
user.setUserName("小红");
user.setPassWord("hello world");
userDao.saveUser(user);
Person person = new Person();
person.setId(2L);
person.setPassWord("111");
person.setUserName("xixi");
person.setAge(11);
person.setName("zhang");
userDao.saveUser(person);
}
增加了person对象的保存,清空掉user集合中的文档,执行保存方法,查看数据如下:
可以看到,有_class的文档将兑现所属的类都标出来了,那么我们测试一下
执行下面的方法
@Test
public void findUserByUserName(){
User user= userDao.findUserByUserName("xixi");
System.out.println("user is "+user + ",得到的对象的类型是:" + user.getClass());
}
结果如下:
执行下面的方法:
@Test
public void findUserByUserName(){
User user= userDao.findUserByUserName("小红");
System.out.println("user is "+user + ",得到的对象的类型是:" + user.getClass());
}
结果如下:
可以看到,对象所属的类是正确的,这个时候,我们在配置去除_class的配置类
清空user集合中的文档,重新数据到mongodb
查看数据
没有了_class属性
执行下面代码
@Test
public void findUserByUserName(){
User user= userDao.findUserByUserName("xixi");
System.out.println("user is "+user + ",得到的对象的类型是:" + user.getClass());
}
结果如下:
xixi查出来的对象应该是属于类Person的,但是得到的结果却是User(Person的父类),得到了和预期不同的结果
那么我们再接着测试下面的:
执行方法
@Test
public void findUserByUserName(){
User user= userDao.findUserByUserName("小红");
System.out.println("user is "+user + ",得到的对象的类型是:" + user.getClass());
}
结果:
这个结果就是正确的.
那么得出的结论就是:当去除了_class属性后,查询出来的对象类型都是其父类,而不能具体到期真实的子类了,这就是spring-data自动添加_class属性到文档中的作用了....