Springboot+MongoDB

springboot整合MongoDB我愣是搞了一整天,

网上那各种简单的一匹的操作,到我这里就报错,搞无语了,属于是无能狂怒

个人整合最终步骤如下:

  1.Spring Initializr新建项目,jdk1.8,java8,这里的依赖就选个"Spring Data MongoDB"就行(甚至可以不选,下面我会给出pom.xml代码)【我这里的springboot版本为2.7.2】

  2.确认有如下依赖(如果不行,可以直接用pom.xml):

复制代码
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
核心依赖
复制代码
复制代码
<?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 https://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.7.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>MG</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web-services</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

<!--        mongo-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
pom.xml
复制代码

  3.配置MongoDB连接:(通用语句:spring.data.mongodb.uri=mongodb://localhost:27017/test)

复制代码
spring.data.mongodb.uri=mongodb://账号:密码@mongodb_host:27017/user?authSource=admin&authMechanism=SCRAM-SHA-1
#spring.data.mongodb.authentication-database=admin
#spring.data.mongodb.password=root
#spring.data.mongodb.username=Root123700
application.properties格式参考
复制代码

  4.下面是三层架构配置

    1.Dao层:

复制代码
package mg.demo.domain;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import java.time.LocalDateTime;

@Data
//指定要对应的文档名(表名)
@Document(collection = "user")
public class User {
    /*** 自定义mongo主键 加此注解可自定义主键类型以及自定义自增规则
     *  若不加 插入数据数会默认生成 ObjectId 类型的_id 字段
     *  org.springframework.data.annotation.Id 包下
     *  mongo库主键字段还是为_id 。不必细究(本文实体类中为id)
     */
    @Id
    private Long userId;
    private String userName;
    private LocalDateTime timer;
}
user[对应test数据库中的user集合]
复制代码

    2.Service层:

复制代码
package mg.demo.service;

import mg.demo.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
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.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.regex.Pattern;

@Service
public class UserService {
    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 新增用户
     */
    public int insertUser(User user){
        try {
            user.setTimer(LocalDateTime.now());
            mongoTemplate.insert(user);
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }

    /**
     * 根据Id修改 ,如需其他条件 修改Query 查询条件即可
     */
    public int updateUser(User user) {
        //通过query根据id查询出对应对象,通过update对象进行修改
        Query query = new Query(Criteria.where("userId").is(user.getUserId()));
        Update update = new Update().set("userName", user.getUserName());
        try {
            mongoTemplate.updateFirst(query, update, User.class);
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }

    /**
     * 根据id删除,如需其他删除条件,修改对应Query对象即可
     */
    public int removeUser(Long id) {
        Query query=new Query(Criteria.where("userId").is(id));
        try {
            mongoTemplate.remove(query,User.class);
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }

    /**
     * 查询一个
     */
    public User findOne(User user) {
        Query query = new Query(Criteria.where("userId").is(user.getUserId()));
        User one = mongoTemplate.findOne(query, User.class);
        return one;
    }
    /**
     * 查询集合-模糊匹配
     */
    public List<User> findlike(User user) {
        Pattern pattern = Pattern.compile("^.*" + user.getUserName().trim() + ".*$", Pattern.CASE_INSENSITIVE);
        Query query = new Query(Criteria.where("userName").regex(pattern));
        List<User> userList = mongoTemplate.find(query, User.class);
        return userList;
    }

    /**
     * 查询集合-精确匹配
     */
    public List<User> findmore(User user) {
        Query query = new Query(Criteria.where("userName").is(user.getUserName()));
        List<User> users = mongoTemplate.find(query, User.class);
        return users;
    }

    /**
     * 倒叙排列查询
     */
    public List<User> findtime(User user) {
        Query query = new Query();
        Query with = query.with(Sort.by(Sort.Direction.DESC, "timer"));
        List<User> users = mongoTemplate.find(query, User.class);
        return users;
    }

    /**
     * MongoDB分页查询
     */
    public List<User> findtimeByPage(User user) {
        Query query = new Query();
        query.with(Sort.by(Sort.Direction.DESC, "timer"));
        query.skip(0).limit(3);
        List<User> users = mongoTemplate.find(query, User.class);
        return users;
    }

}
UserService
复制代码

    3.Controller层:

复制代码
package mg.demo.controller;

import mg.demo.domain.User;
import mg.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {
    @Autowired
    UserService userService;
    @RequestMapping("insertUser/{id}")
    public String insertUser(@PathVariable("id") long id){
        User user = new User();
        user.setUserId(id);
        user.setUserName("张三" + id);
        userService.insertUser(user);
        return "insert succ";
    }
    @RequestMapping("updateUser")
    public String updateUser() {
        User user = new User();
        user.setUserId(1234L);
        user.setUserName("张三");
        userService.updateUser(user);
        return "update succ";
    }
    @RequestMapping("removeUser")
    public String removeUser(){
        userService.removeUser(1234L);
        return "remove succ";
    }
    @RequestMapping("getUser")
    public String getUser(){
        User user = new User();
        user.setUserId(1234L);
        return userService.findOne(user).toString();
    }

}
UserController
复制代码

  5.监听配置类:

复制代码
package mg.demo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter;

/***
 * @description: MongoDB监听配置, 此类若不加,那么插入的一行会默认添加一个_class字段来存储实体类类型 如(com.duoduo.mongodb.entity.User)
 */
@Configuration
public class ApplicationReadyListener implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    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));
        }
    }
}
ApplicationReadyListener
复制代码

  6.正常情况这里就已经齐全了所有基本构建了,但是可能会报错:MongoTemplate注入失败

原因是springboot版本已经不支持自动注入了,需要自己配置:

复制代码
package mg.demo.config;

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;

@Configuration
public class MongoDBConfig {
    @Bean
    public MongoClient mongoClient() {
        return MongoClients.create("mongodb://localhost:27017");
    }
    @Bean
    public MongoTemplate mongoTemplate() {
        return new MongoTemplate(mongoClient(), "test");
    }
}
MongoDBConfig
复制代码

最终项目结构大致如下:

 

 

鸣谢博客:基本配置here,MongoTemplate配置here

 

----------------------------一个问题----------------------------

  在比较高版本的springboot不再能自动注入mongo的bean容器。

  答:可以手动写配置类来注入。

  但是这样就不能很好的使用properties或者yml配置文件,甚至当mongodb配置了登录认证后,目前网上教程来看,手动写能够满足登录认证的配置类,我是不行了,2022/08/04我被折磨了一整天,使用的springboot版本号是[2.7.2]。

  当我放弃,选择尝试去找较低版本的springboot来使用,结果发现springboot[2.6]就可以,甚至[2.6.10]也可以。(哀嚎嘤嘤嘤脸) 

-----------------------我服了----------------------------------

上面那个问题没法手动写出配置类的原因是因为我把登录的用户账号密码写错了。。。。

换个写法就行。。。。。。。。。。黄豆流汗脸。。。。。。。。。。

配置如下:

复制代码
package mg.demo.config;

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;

@Configuration
public class MongoDBConfig {
    @Bean
    public MongoClient mongoClient() {
//        return MongoClients.create("mongodb://localhost:27017");// 无认证
        return MongoClients.create("mongodb://root:root@localhost:27017");// 有认证
    }

    @Bean
    public MongoTemplate mongoTemplate() {
        return new MongoTemplate(mongoClient(), "test");
    }
}
MongoDBConfig
复制代码

 

-----------------------------------------------Mongodb开发技巧-----------------------------------------------------------------

1.常用注解,参考:here

 

2.因为MongoTemplate已经封装好了基本的操作,所以【简单的项目,不需要写Dao层,Service层,就实体类和使用MongoTemplate的Controller层即可使用】

 

  (需要注意的是,在写接口时候,注意区分接口,不然会报错:“ambiguous mapping”)

 

  参考结构:

 

                            

3.Mongodb也可以实现主键Id自动增长,自己写,我暂时没用到,就不贴代码了。

-----------------------------------------------下面记录开发bug-----------------------------------------------------------------

1.插入数据报错:Cannot autogenerate id of type java.lang.Integer for entity of type

  意思是在说,mongo无法自动生成实体类的主键键值,但是操作过命令行的都知道Mongodb是能够自动补全主键为"_id"列的。

(MongoDB在不特殊指认的情况下,默认的集合主键是“_id”,类型是ObjectId。ObjectId是一个12字节的BSON类型字符串,包含了UNIX时间戳,机器识别码,进程号,计数值信息。机器码用来防止分布式系统生成id时冲突的问题,保证每台机器生成的识别码不同,进程号保证多线程情况下生成的id不同。)

这里不能生成的原因是因为entity实体类里面写的映射主键类型不能与默认类型"ObjectId"进行相互转化,所以报错。

  解决办法:去掉entity的Id字段或者将Id字段的数据类型改为String或者ObjectId

2.同步请求(修改+查询)的查询结果修改无效,但是实际查看数据库是已经修改了的。

  原因是因为,mongodb的操作分为:内存和数据库,当在内存里修改后就立即返回修改成功结果,原code立马同步请求查询,导致查询数据库的数据的查询结果(有概率)为未修改的数据。

  

 

【Over】

posted @   Renhr  阅读(859)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
点击右上角即可分享
微信分享提示