一,springboot整合mongodb

如需转载,请标明出处:https://zhenghuisheng.blog.csdn.net/article/details/139704356

此篇主要讲解在java中,如何通过springboot项目去操作mongodb,如何创建springboot项目此处省略

1,依赖加入

在pom文件中,加入对应的依赖,版本需要于springboot的版本对应

<dependency>
	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
    <version>2.3.9.RELEASE</version>
</dependency>

2,yml文件配置

首先进入配置阶段,在yml配置文件中加入以下配置,如果在安装之后的auth设置为false,那么不需要账号密码也能直接访问

spring:  
  data:
    mongodb:
      host: xxx.xxx.xxx.xxx
      port: 27017
      username: zhs
      password: 'zhs123456'
      database: archive
      authentication-database: admin

也可以用下面这种方式,uri方式和上面的参数不要重复,只能只使用一种,推荐使用上面这种,可读性强

spring:
  data:
    mongodb:
      uri: "mongodb://zhs:zhs123456@xxx.xxx.xxx.xxx:27017/archive"

3,_class 字段过滤(可选)

在实体类数据存入到mongodb时,会将这个 _class 实体类对应的类全路径也存到mongodb中,我这边不需要这个数据,几亿条数据都加一个这个实体类对象,除了占磁盘之外毫无意义,因此我这边选择将这个字段去掉,定义一个MongoConfig实体类,再注入到容器中即可

@Configuration
public class MongoConfig implements ApplicationListener<ContextRefreshedEvent> {
    @Resource
    MongoTemplate oneMongoTemplate;

    private static final String TYPEKEY = "_class";

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        MongoConverter converter = oneMongoTemplate.getConverter();
        if (converter.getTypeMapper().isTypeKey(TYPEKEY)) {
            ((MappingMongoConverter) converter).setTypeMapper(new DefaultMongoTypeMapper(null));
        }
    }
}

4,实体类定义

接下来定义一个User实体类作为测试用,通过这个Field注解实现实体类字段和mongodb的字段相关联,mongodb不需要像mysql一样需要提前建表,建好实体类就可以对mongodb中的集合进行操作了,User实体类就会对应Mongodb中的一个集合,相当于mysql的一张表,每条数据就是一个文档,每个文档大小限制16m

@Data
public class User {
    @Field("_id")
    private String id;
    
    @Field("username")
    private String username;

    @Field("password")
    private String password;
    
    //更新时间
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Field("updatedTime")
    private Date updatedTime;

    //创建时间
    @Field("createdTime")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createdTime;
}

5,索引创建

都使用mongodb了,后期数据量肯定是非常大的,不然也不可能考虑使用这个玩意儿。因此在文档建好之后,最好提前把索引建上。这里直接选择使用username 和 password作为唯一的联合索引。索引的建立根据实际业务考虑,不能确定是唯一就建普通索引

//user表示哪个集合
db.user.createIndex({username: 1,password:1}, {unique: true})

6,数据插入

mongodb有两种方法实现数据插入,一种是直接使用insert或者insertAll的方式插入,另一种是通过save的方式插入数据

6.1,insert方式

如果直接选择insert的方式插入数据,那么他会判断数据库中是否有这条数据,如通过id判断,如果已经有id为1的用户,再次插入id为1的用户数据时,那么就会直接抛一个异常出来,并且会让整个操作失败。代码如下,如果没有设置id,那么mongodb会自动设置一个唯一的uuid作为id,我这边直接使用一个雪花算法生成的id

User user = new User();
user.setId(SnowflakeUtils.nextId());  //该工具类需要自行生成,可百度
user.setUsername("zhs");
user.setPassword("123456");
user.setCreatedTime(new Date());
user.setUpdatedTime(new Date());
mongoTemplate.insert(user);

也可以直接使用一个批量插入的方式将数据插入,这样将多次io直接转换成1次io,效率更高

List<User> list = new ArrayList<>();
User user = new User();
...
list.add(user);
mongoTemplate.insertAll(list);
6.2,使用save的方式实现

整体操作和insert的一样,在数据插入时使用save方法。使用save方法可以让整体变得更加灵活,insert在集合中已经存在的文档id再插入时会直接抛出异常,但是save不会,会直接进行更新的操作,如果数据不存在则会插入操作。但是在此期间,每次save时需要遍历全部数据,判断数据是否存在,在效率上是远远不及这个insert的

User user = new User();
user.setId(SnowflakeUtils.nextId());  //该工具类需要自行生成,可百度
user.setUsername("zhs");
user.setPassword("123456");
user.setCreatedTime(new Date());
user.setUpdatedTime(new Date());
mongoTemplate.save(user);

综上所述,最好就是每次自定义的生成一个唯一id,然后使用insert去操作数据

7,数据更新

7.1,update普通方式更新

数据更新的方式如下,如果只需要更新一条数据,如下面代码。上面我根据username和password建立了唯一索引,因此只需要updateFirst更新一条数据即可

Query query = new Query();
query.addCriteria(Criteria.where("username").is("zhs"));
query.addCriteria(Criteria.where("password").is("zhs123456"));
Update update = new Update().set("password","zhs12345678");
mongoTemplate.updateFirst(query,update, User.class);

也可以通过这个updateMulti实现多条数据的更新,如下面将所有用户名为zhs的更新时间修改

Query query = new Query();
query.addCriteria(Criteria.where("username").is("zhs"));
Update update = new Update().set("updatedTime",new Date());
mongoTemplate.updateMulti(query,update,User.class);
7.2,BulkOperations 方式更新

上面这些事针对同一个where条件的,也可以针对不同更新文档实现批量更新,这里可以使用 BulkOperations 操作。如更新名为 zhs的密码为 zhs12345678,更新名为 zhsqaq 的密码为 zhsqaq12345678 ,总而言之就是将多条毫无关联的的更新语句一次更新完成

//创建一个BulkOperations实例
BulkOperations updateBulkOps = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, "User");

创建完这个 BulkOperations 实例之后,接下来就是可以去创建多条更新语句,随后在构建完的查询与句话中,调用这个updateBulkOps.updateOne方法,再最后调用这个excute方法,将这些全部聚合的更新操作全部执行

//构建查询条件1
Query query1 = new Query();
query1.addCriteria(Criteria.where("username").is("zhs"));
query1.addCriteria(Criteria.where("password").is("zhs123456"));
Update update1 = new Update().set("password","zhs12345678");
updateBulkOps.updateOne(query1,update1);
//构建查询条件2
Query query2 = new Query();
query2.addCriteria(Criteria.where("username").is("zhsqaq"));
query2.addCriteria(Criteria.where("password").is("zhsqaq123456"));
Update update2 = new Update().set("password","zhsqaq12345678");
updateBulkOps.updateOne(query2,update2);
...
//执行这个操作
updateBulkOps.execute();

8,数据查询

查询这块方式比较多也比较简单,接下来讲解集中简单的查询方式,如下直接查询全部文档

List<User> userList = mongoTemplate.findAll(User.class);

也可以通过Query构造条件查询,并通过这 Criteria 条件构造条件去筛选数据

Query query2 = new Query();
query2.addCriteria(Criteria.where("username").is("zhsqaq"));
query2.addCriteria(Criteria.where("password").is("zhsqaq123456"));
mongoTemplate.find(query, User.class)

除了上面的is,还有可多api都是可用的,如一些基本操作ne,lt ,lte ,gt , gte 等等,基本操作运算符和比较运算符里面都有的

【Mongodb-02】springboot整合mongodb(详解)-LMLPHP

还支持在查询条件中增加排序功能,支持升序和降序,如下面这条根据创建时间升序排序

query.with(Sort.by(Sort.Order.asc("createdTime")));

同时支持分页功能,如继续给查询条件中返回前100条数据

query.skip(0).limit(100);

获取某个集合总文档的个数如下

mongoTemplate.count(query,User.class);

9,数据删除

数据删除就比较简单,只需要构造查询的条件,调用remove方法就可以直接将数据删除,如删除用户名为zhs的用户的数据

Query query = new Query();
query.addCriteria(Criteria.where("username").is("zhs"));
mongoTemplate.remove(query,User.class); //删除符合的数据

到此为止spring Boot整合mongodb算是入门成功

除就比较简单,只需要构造查询的条件,调用remove方法就可以直接将数据删除,如删除用户名为zhs的用户的数据

Query query = new Query();
query.addCriteria(Criteria.where("username").is("zhs"));
mongoTemplate.remove(query,User.class); //删除符合的数据

到此为止spring Boot整合mongodb算是入门成功

06-16 14:10