SpringBoot结合MongoDB入门
MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它可以存储多种数据结构,类似 json 的 bson,可以存储复杂数据类型。
它最大的特点就是支持的查询语言非常强大,其语法类似面向对象的方式,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
在传统关系型数据库一般由:数据库(database),表(table), 数据记录(record)三个概念层次组成,而 MongoDB 是由 数据库(database),集合(collection),文档对象(document)三个层级组成。
MongoDB 中集合对应了关系型数据库中的表,但是集合中没有列、行、约束关系的概念,体现了它模式自由的特点,存储数据结构的自由。MongDB 中存储的一条记录就是一个文档,是一个数据结构(类似 ElasticSearch),
由字段和值组成。MongoDB 文档与 JSON 对象类似。字段的值有可能包括其它文档、数组以及文档数组。
MongoDB 适合对大量或者无固定格式的数据进行存储,比如:日志、缓存、文本数据等,对事务的支持比较弱,不适合多文档(多表)级联查询。
下面介绍一下 MongoDB 的增删改查:
Spring Boot 对各种流行的数据源都进行了封装,当然也包括了 mongodb, 下面给大家介绍如何在 spring boot 中使用 mongodb:
1、pom 包配置
引入 spring-boot-starter-data-mongodb 包
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> </dependencies>
2、在 application.properties 中添加配置
spring.data.mongodb.uri=mongodb://user:pass@localhost:27017/test
若是本地连接:spring.data.mongodb.uri=mongodb://localhost:27017/test
多个 IP 集群可以采用以下配置:
spring.data.mongodb.uri=mongodb://user:pwd@ip1:port1,ip2:port2/database
2、创建数据实体
public class UserEntity implements Serializable { private static final long serialVersionUID = -3258839839160856613L; private Long id; private String userName; private String passWord;</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">getter、setter省略</span>
}
3、创建实体 dao 的增删改查操作
dao 层实现了 UserEntity 对象的增删改查
@Component public class UserDaoImpl implements UserDao {@Autowired </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> MongoTemplate mongoTemplate; </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 创建对象 * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> user </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> @Override </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> saveUser(UserEntity user) { mongoTemplate.save(user); } </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 根据用户名查询对象 * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> userName * </span><span style="color: rgba(128, 128, 128, 1)">@return</span> <span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> @Override </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> UserEntity findUserByUserName(String userName) { Query query</span>=<span style="color: rgba(0, 0, 255, 1)">new</span> Query(Criteria.where("userName"<span style="color: rgba(0, 0, 0, 1)">).is(userName)); UserEntity user </span>= mongoTemplate.findOne(query , UserEntity.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> user; } </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 更新对象 * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> user </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> @Override </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> updateUser(UserEntity user) { Query query</span>=<span style="color: rgba(0, 0, 255, 1)">new</span> Query(Criteria.where("id"<span style="color: rgba(0, 0, 0, 1)">).is(user.getId())); Update update</span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Update().set("userName", user.getUserName()).set("passWord"<span style="color: rgba(0, 0, 0, 1)">, user.getPassWord()); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">更新查询返回结果集的第一条</span> mongoTemplate.updateFirst(query,update,UserEntity.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">更新查询返回结果集的所有 </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> mongoTemplate.updateMulti(query,update,UserEntity.class);</span>
}
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 删除对象 * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> id </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> @Override </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> deleteUserById(Long id) { Query query</span>=<span style="color: rgba(0, 0, 255, 1)">new</span> Query(Criteria.where("id"<span style="color: rgba(0, 0, 0, 1)">).is(id)); mongoTemplate.remove(query,UserEntity.</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); }
}
4、对应的测试方法
@RunWith(SpringRunner.class) @SpringBootTest public class UserDaoTest {@Autowired </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> UserDao userDao; @Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> testSaveUser() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception { UserEntity user</span>=<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> UserEntity(); user.setId(</span>2l<span style="color: rgba(0, 0, 0, 1)">); user.setUserName(</span>"小明"<span style="color: rgba(0, 0, 0, 1)">); user.setPassWord(</span>"fffooo123"<span style="color: rgba(0, 0, 0, 1)">); userDao.saveUser(user); } @Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> findUserByUserName(){ UserEntity user</span>= userDao.findUserByUserName("小明"<span style="color: rgba(0, 0, 0, 1)">); System.out.println(</span>"user is "+<span style="color: rgba(0, 0, 0, 1)">user); } @Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> updateUser(){ UserEntity user</span>=<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> UserEntity(); user.setId(</span>2l<span style="color: rgba(0, 0, 0, 1)">); user.setUserName(</span>"天空"<span style="color: rgba(0, 0, 0, 1)">); user.setPassWord(</span>"fffxxxx"<span style="color: rgba(0, 0, 0, 1)">); userDao.updateUser(user); } @Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> deleteUserById(){ userDao.deleteUserById(</span>1l<span style="color: rgba(0, 0, 0, 1)">); }
}
5、查验结果
可以使用工具 mongoVUE 工具来连接后直接图形化展示查看,也可以登录服务器用命令来查看
1. 登录 mongos
bin/mongo -host localhost -port 20000
2、切换到 test 库
use test
3、查询 userEntity 集合数据
db.userEntity.find()
根据 3 查询的结果来观察测试用例的执行是否正确。
到此 springboot 对应 mongodb 的增删改查功能已经全部实现。
多数据源 mongodb 的使用
在多 mongodb 数据源的情况下,我们换种更优雅的方式来实现
1、pom 包配置
添加 lombok 和 spring-boot-autoconfigure 包引用
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>RELEASE</version> </dependency>
-
Lombok - 是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的 Java 代码的工具,通过使用对应的注解,可以在编译源码的时候生成对应的方法。简单试了以下这个工具还挺好玩的,加上注解我们就不用手动写 getter\setter、构建方式类似的代码了。
-
spring-boot-autoconfigure - 就是 spring boot 的自动化配置
2、配置文件使用 YAML 的形式添加两条数据源,如下:
mongodb: primary: host: 192.168.9.60 port: 20000 database: test secondary: host: 192.168.9.60 port: 20000 database: test1
3、配置两个库的数据源
封装读取以 mongodb 开头的两个配置文件
@Data @ConfigurationProperties(prefix = "mongodb") public class MultipleMongoProperties {</span><span style="color: rgba(0, 0, 255, 1)">private</span> MongoProperties primary = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MongoProperties(); </span><span style="color: rgba(0, 0, 255, 1)">private</span> MongoProperties secondary = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MongoProperties();
}
配置不同包路径下使用不同的数据源
第一个库的封装
@Configuration @EnableMongoRepositories(basePackages = "com.neo.model.repository.primary", mongoTemplateRef = PrimaryMongoConfig.MONGO_TEMPLATE) public class PrimaryMongoConfig {</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String MONGO_TEMPLATE = "primaryMongoTemplate"<span style="color: rgba(0, 0, 0, 1)">;
}
第二个库的封装
@Configuration @EnableMongoRepositories(basePackages = "com.neo.model.repository.secondary", mongoTemplateRef = SecondaryMongoConfig.MONGO_TEMPLATE) public class SecondaryMongoConfig {</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String MONGO_TEMPLATE = "secondaryMongoTemplate"<span style="color: rgba(0, 0, 0, 1)">;
}
读取对应的配置信息并且构造对应的 MongoTemplate
@Configuration public class MultipleMongoConfig {@Autowired </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> MultipleMongoProperties mongoProperties; @Primary @Bean(name </span>=<span style="color: rgba(0, 0, 0, 1)"> PrimaryMongoConfig.MONGO_TEMPLATE) </span><span style="color: rgba(0, 0, 255, 1)">public</span> MongoTemplate primaryMongoTemplate() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception { </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> MongoTemplate(primaryFactory(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.mongoProperties.getPrimary())); } @Bean @Qualifier(SecondaryMongoConfig.MONGO_TEMPLATE) </span><span style="color: rgba(0, 0, 255, 1)">public</span> MongoTemplate secondaryMongoTemplate() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception { </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> MongoTemplate(secondaryFactory(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.mongoProperties.getSecondary())); } @Bean @Primary </span><span style="color: rgba(0, 0, 255, 1)">public</span> MongoDbFactory primaryFactory(MongoProperties mongo) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception { </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> SimpleMongoDbFactory(<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MongoClient(mongo.getHost(), mongo.getPort()), mongo.getDatabase()); } @Bean </span><span style="color: rgba(0, 0, 255, 1)">public</span> MongoDbFactory secondaryFactory(MongoProperties mongo) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception { </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> SimpleMongoDbFactory(<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MongoClient(mongo.getHost(), mongo.getPort()), mongo.getDatabase()); }
}
至此,两个库的配置信息已经完成。
4、创建两个库分别对应的对象和 Repository
借助 lombok 来构建对象
@Data @AllArgsConstructor @NoArgsConstructor @Document(collection = "first_mongo") public class PrimaryMongoObject {@Id </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String id; </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String value; @Override </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String toString() { </span><span style="color: rgba(0, 0, 255, 1)">return</span> "PrimaryMongoObject{" + "id='" + id + '\'' + ", value='" + value + '\'' + '}'<span style="color: rgba(0, 0, 0, 1)">; }
}
对应的 Repository
public interface PrimaryRepository extends MongoRepository<PrimaryMongoObject, String> { }
继承了 MongoRepository 会默认实现很多基本的增删改查,省了很多自己写 dao 层的代码
5、最后测试
@RunWith(SpringRunner.class) @SpringBootTest public class MuliDatabaseTest {@Autowired </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> PrimaryRepository primaryRepository; @Autowired </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> SecondaryRepository secondaryRepository; @Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> TestSave() { System.out.println(</span>"************************************************************"<span style="color: rgba(0, 0, 0, 1)">); System.out.println(</span>"测试开始"<span style="color: rgba(0, 0, 0, 1)">); System.out.println(</span>"************************************************************"<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.primaryRepository .save(</span><span style="color: rgba(0, 0, 255, 1)">new</span> PrimaryMongoObject(<span style="color: rgba(0, 0, 255, 1)">null</span>, "第一个库的对象"<span style="color: rgba(0, 0, 0, 1)">)); </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.secondaryRepository .save(</span><span style="color: rgba(0, 0, 255, 1)">new</span> SecondaryMongoObject(<span style="color: rgba(0, 0, 255, 1)">null</span>, "第二个库的对象"<span style="color: rgba(0, 0, 0, 1)">)); List</span><PrimaryMongoObject> primaries = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.primaryRepository.findAll(); </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (PrimaryMongoObject primary : primaries) { System.out.println(primary.toString()); } List</span><SecondaryMongoObject> secondaries = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.secondaryRepository.findAll(); </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (SecondaryMongoObject secondary : secondaries) { System.out.println(secondary.toString()); } System.out.println(</span>"************************************************************"<span style="color: rgba(0, 0, 0, 1)">); System.out.println(</span>"测试完成"<span style="color: rgba(0, 0, 0, 1)">); System.out.println(</span>"************************************************************"<span style="color: rgba(0, 0, 0, 1)">); }
}