SpringBoot+Mongodb的使用

Mongodb基础命令、代码集成、日志管理、多数据源配置

本文只要讲解一下Mongodb的安装、基本命令、Java代码集成、保存运行日志、以及多数据源的配置。

1、Mongodb安装

首先在mongodb官网下载自己想要的版本。
下载地址:https://www.mongodb.com/download-center?jmp=nav#community
安装教程:http://www.runoob.com/mongodb/mongodb-window-install.html
Mongodb可视化工具:https://robomongo.org/download
最新版本的Mongodb会创建Monodb服务。无需用户自己创建服务。Mongodb默认没有用户名与密码且不开启用户授权模式,安全性极低。因此需要开启用户授权模式。

2、开启授权模式

和其他所有数据库一样,权限的管理都差不多一样。mongodb存储所有的用户信息在admin 数据库的集合system.users中,保存用户名、密码和数据库信息。mongodb默认不启用授权认证,只要能连接到该服务器,就可连接到mongod。若要启用安全认证,需要更改配置文件参数auth。
新安装的mongodb是没有用户名和密码的,需要自己新建。在没有开始授权模式的情况下,可以不使用用户名密码进行连接并且访问数据。开始授权模式也可以不使用密码进行连接,但是无法进行访问操作。如下图所示会报错。
这里写图片描述
1、首先创建用户,需要写入用户的用户名、密码以及角色。Mongodb内置了大量角色。大家感兴趣的话可以看下官方文档。

db.createUser({user:"root",pwd:"root",roles:["root"]})  

2、编辑安装目录的mongod.cfg文件,增加以下配置

security:
    authorization: enabled

3、重启Mongodb服务

Mongodb的基本命令

show dbs;                  #查看全部数据库
show collections/tables;   #显示当前数据库中的集合(类似关系数据库中的表)
show users;                #查看当前数据库的用户信息
use <db name>;             #切换数据库跟mysql一样
db                         #操作的数据库名称
db.help();                 #显示数据库操作命令,里面有很多的命令 
db.dropDatabase();         #删除当前使用数据库  
db.COLLECTION_NAME.drop(); #删除集合 

##mongodb不用手动创建数据库与集合只需要在数据库和集合中插入数据则会自动创建
##MongoDb客户端驱动会自动为你生成一个默认ObjectId作为_id。

db.COLLECTION_NAME.insert() #若新增数据的主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常提示主键重复,不保存当前数据。
db.COLLECTION_NAME.save()   #若新增数据的主键已经存在,则会对当前已经存在的数据进行修改操作。

db.COLLECTION_NAME.getIndexes()  #查看集合中的索引   
db.COLLECTION_NAME.createIndex(keys, options)   语法中 Key 值为你要创建的索引字段,1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可。

db.COLLECTION_NAME.update({name:"lixiang"},{$set:{age:18}}) #不会影响其他属性列
db.COLLECTION_NAME.update({name:"lixiang"},{$set:{age:18}},true)#第三个参数为true 则执行insertOrUpdate操作,查询出则更新,没查出则插入,

db.COLLECTION_NAME.find(name:"lixiang")   #条件查询
db.COLLECTION_NAME.find({name:{$regex:/lixiang/}})  #模糊查询  regex关键字

db.COLLECTION_NAME.remove({name:"lixiang"})  #条件删除
db.COLLECTION_NAME.deleteMany({})   #删除集合中全部的数据

SpringBoot代码集成、日志管理

pom.xml依赖如下:高版本的springboot可能无法同时使用日志管理与mongodb的增删改查。我使用的是1.5.1.RELEASE的springboot。

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.14.2</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.4</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.6.1</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.6.1</version>
        </dependency>

        <!-- spring-boot-starter-data-mongodb -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>

        <!-- log4j2 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
        <dependency>  <!-- 加上这个才能辨认到log4j2.yml文件 -->
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-yaml</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-nosql</artifactId> <!-- 必需,否则报错 -->
            <version>2.7</version>
        </dependency>

        <!-- mongodb driver -->
        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongodb-driver</artifactId>
            <version>3.2.2</version>
        </dependency>
    </dependencies>

application.properties配置文件如下:

#配置mongodb信息
spring.data.mongodb.host=127.0.0.1
spring.data.mongodb.port=27017
spring.data.mongodb.database=mongoTest
spring.data.mongodb.username=mongoTest
spring.data.mongodb.password=root

#控制nosql语句
logging.level.org.springframework.data.mongodb.core= DEBUG

代码中集成Swagger方便进行测试。Controller代码如下:(主要讲一下MongoTemplate 怎么进行简单的数据操作以及常用的方法说明)

package cn.thislx.mongodbsimple.demo.controller;

import cn.thislx.mongodbsimple.demo.entity.*;
import com.alibaba.fastjson.JSON;
import com.mongodb.WriteResult;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
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.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: LX
 * @Description: 使用mongoTemplate进行常用数据操作
 * @Date: Created in 16:18 2018/7/23
 * @Modified by:
 */
@RestController
public class MongodbController {

    @Resource
    private MongoTemplate mongoTemplate;

    /**
     * @param student: 保存的对象
     * @Author: LX
     * @Description: mongodb进行数据的单一保存
     * @Date: 2018/7/23 16:56
     * @Modified by:
     */
    @ApiOperation(value = "单一保存", notes = "单一保存对象")
    @PostMapping("/singleSave")
    public Student singleSave(@RequestBody Student student) {
        mongoTemplate.insert(student);
        return student;
    }

    /**
     * @param classes: 保存的对象
     * @Author: LX
     * @Description: 内嵌保存数据,eg:保存一个班级和班级中的学生集合
     * @Date: 2018/7/25 13:21
     * @Modified by:
     */
    @ApiOperation(value = "嵌套保存", notes = "嵌套保存对象")
    @PostMapping("/nestSave")
    public Classes nestSave(@RequestBody Classes classes) {
        //使用fastJson将对象转化为Json
        String json = JSON.toJSONString(classes);
        mongoTemplate.insert(json, "class");
        return classes;
    }


    /**
     * @param classId: 班级Id
     * @Author: LX
     * @Description: 根据单条件进行删除
     * @Date: 2018/7/25 13:26
     * @Modified by:
     */
    @ApiOperation(value = "简单删除", notes = "简单删除")
    @PostMapping("/singleDelete")
    public Map<String, String> singleDelete(@RequestBody String classId) {
        Map<String, String> map = new ConcurrentHashMap<String, String>();
        try {
            Query query = new Query(Criteria.where("classId").is(classId));
            WriteResult aClass = mongoTemplate.remove(query, "class");
            map.put("result", "success");
            map.put("msg", "删除成功共" + aClass.getN() + "条数据");
        } catch (Exception e) {
            map.put("result", "failed");
            map.put("msg", "删除失败");
            e.printStackTrace();
        }
        return map;
    }


    /**
     * @param condition:嵌套删除数据的参数
     * @Author: LX
     * @Description: 使用upsert进行嵌套删除这种方法有一个缺陷,会将符合条件的数据修改成null,而不会进行实际删除
     * @Date: 2018/7/24 18:06
     * @Modified by:
     */
    @ApiOperation(value = "upsert删除嵌套数据", notes = "删除嵌套数据")
    @PostMapping("/upsertNestDelete")
    public Map<String, String> upsertNestDelete(@RequestBody Condition condition) {
        Map<String, String> map = new ConcurrentHashMap<String, String>();
        try {
            Query query = Query.query(Criteria.where("classId").is(condition.getClassId()).
                    and("students.studentId").is(condition.getStudent().getStudentId()));
            Update update = new Update();
            update.unset("students.$");
            WriteResult aClass = mongoTemplate.upsert(query, update, "class");
            map.put("result", "success");
            map.put("msg", "嵌套删除成功共" + aClass.getN() + "条数据");

        } catch (Exception e) {
            e.printStackTrace();
            map.put("result", "failed");
            map.put("msg", "嵌套删除失败");
        }
        return map;
    }


    /**
     * @param condition:嵌套删除数据的参数
     * @Author: LX
     * @Description: 如果要彻底删除,则需要使用pull(pull删除内嵌文档的时候,student对象的值一定要和被删除的一模一样)
     * @Date: 2018/7/24 18:06
     * @Modified by:
     */
    @ApiOperation(value = "pull删除嵌套数据", notes = "删除嵌套数据")
    @PostMapping("/pullNestDelete")
    public Map<String, String> pullNestDelete(@RequestBody Condition condition) {
        Map<String, String> map = new ConcurrentHashMap<String, String>();
        try {
            Query query = Query.query(Criteria.where("classId").is(condition.getClassId()));
            Update update = new Update();
            update.pull("students", condition.getStudent());
            WriteResult aClass = mongoTemplate.upsert(query, update, "class");
            map.put("result", "success");
            map.put("msg", "pull删除嵌套数据" + aClass.getN() + "条数据");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("result", "failed");
            map.put("msg", "嵌套删除失败");
        }
        return map;
    }


    /**
     * @param condition: 查询内嵌对象参数封装
     * @Author: LX
     * @Description:内嵌条件查询 eg:查询101班级名字叫lisi的学生
     * @Date: 2018/7/25 13:24
     * @Modified by:
     */
    @ApiOperation(value = "内嵌条件查询", notes = "嵌套条件查询")
    @PostMapping("/nestConditionFind")
    public List<Classes> nestConditionFind(@RequestBody Condition condition) {
        Query query = new Query(Criteria.where("classId").is(condition.getClassId()).
                and("students.name").is(condition.getStudent().getName()));
        List<Classes> aClass = mongoTemplate.find(query, Classes.class, "class");
        return aClass;
    }

    /**
     * @param classId:班级ID
     * @Author: LX
     * @Description:进行单条件查询
     * @Date: 2018/7/25 13:23
     * @Modified by:
     */
    @ApiOperation(value = "单条件查询", notes = "单条件查询")
    @PostMapping("/findById")
    public Map<String, Object> findById(@RequestBody String classId) {
        Map<String, Object> map = new ConcurrentHashMap<String, Object>();
        try {
            Query query = Query.query(Criteria.where("classId").is(classId));
            List<Classes> aClass = mongoTemplate.find(query, Classes.class, "class");
            map.put("result", "success");
            map.put("data", aClass);
        } catch (Exception e) {
            e.printStackTrace();
            map.put("result", "failed");
        }
        return map;
    }

    /**
     * @param condition:分页对象查询参数封装
     * @Author: LX
     * @Description: 分页查询
     * @Date: 2018/7/25 13:29
     * @Modified by:
     */
    @ApiOperation(value = "分页查询", notes = "分页查询")
    @PostMapping("/findClassPage")
    public Map<String, Object> findClassPage(@RequestBody PageCondition<Condition> condition) {
        Map<String, Object> map = new ConcurrentHashMap<String, Object>();
        Criteria criteria = null;
        try {
            //对条件进行非空判断  类似于mybatis中的<if test=""></if>
            if (StringUtils.isNotEmpty(condition.getT().getClassId())) {
                criteria = Criteria.where("classId").is(condition.getT().getClassId());
            } else {
                criteria = Criteria.where("classId").ne(null);
            }

            if (StringUtils.isNotEmpty(condition.getT().getStudent().getName())) {
                criteria.and("student.name").is(condition.getT().getStudent().getName());
            }

            if (StringUtils.isNotEmpty(condition.getT().getStudent().getStudentId())) {
                criteria.and("student.studentId").is(condition.getT().getStudent().getStudentId());
            }
            Query query = Query.query(criteria);
            //创建分页对象
            Pageable pageable = new PageRequest(condition.getCurrentPageNo(), condition.getPageSize());
            query.with(pageable);

            // 排序
            query.with(new Sort(Sort.Direction.ASC, "age"));

            // 查询总数
            int count = (int) mongoTemplate.count(query, Classes.class, "class");
            List<Classes> items = mongoTemplate.find(query, Classes.class, "class");
            Page<List<Classes>> listPage = new Page<>();
            listPage.setCurrentPageNo(condition.getCurrentPageNo());
            listPage.setPageSize(condition.getPageSize());
            listPage.setTotalRows(count);
            listPage.setT(items);
            map.put("data", listPage);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * @param condition: 修改对象
     * @Author: LX
     * @Description: mongodb进行简单的修改  介绍upsert、updateFirst、updateMulti区别
     * @Date: 2018/7/25 13:02
     * @Modified by:
     */
    @PostMapping("/singleUpdate")
    @ApiOperation(value = "简单修改", notes = "简单修改数据")
    public Map<String, Object> singleUpdate(@RequestBody Condition condition) {
        Map<String, Object> map = new ConcurrentHashMap<String, Object>();
        try {
            Query query = Query.query(Criteria.where("classId").is(condition.getClassId()));

            //1、如果不存在修改的此列  mongodb会进行自动创建  没有查询到数据  mongodb也会自动新增一条数据
            Update update = Update.update("teacherName", condition.getTeacherName());
//            WriteResult result = mongoTemplate.upsert(query, update, "class");

            //2、更新满足条件的第一条数据  没有查询到数据不会增加新数据
            //mongoTemplate.updateFirst(query, update, "class");

            //3、更新所有满足条件的数据   没有查询到数据不会增加新数据
            WriteResult writeResult = mongoTemplate.updateMulti(query, update, "class");
            map.put("result", "success");
            map.put("msg", "共简单修改" + writeResult.getN() + "条数据");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("result", "failed");
        }
        return map;
    }


    /**
     * @param condition
     * @Author: LX
     * @Description:保存嵌套数据 介绍push、addToSet在保存中的区别
     * @Date: 2018/7/25 13:04
     * @Modified by:
     */
    @PostMapping("/innerSave")
    @ApiOperation(value = "保存嵌套数据", notes = "保存嵌套数据")
    public Map<String, Object> innerSave(@RequestBody Condition condition) {
        Map<String, Object> map = new ConcurrentHashMap<String, Object>();
        try {
            Query query = Query.query(Criteria.where("classId").is(condition.getClassId()));
            Update update = new Update();

            //1、push如果数据已经存在,会插入一条一样的数据。
            //update.push("students", condition.getStudent());

            //2、addToSet如果数据已经存在,则不做任何操作
            update.addToSet("Students", condition.getStudent());
            WriteResult result = mongoTemplate.upsert(query, update, "class");
            map.put("result", "success");
            map.put("msg", "共简单修改" + result.getN() + "条数据");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("result", "failed");
        }
        return map;
    }


    @PostMapping("/innerUpdate")
    @ApiOperation(value = "修改嵌套数据", notes = "修改嵌套数据")
    public Map<String, Object> innerUpdate(@RequestBody Condition condition) {
        Map<String, Object> map = new ConcurrentHashMap<String, Object>();
        try {
            Query query = Query.query(Criteria.where("classId").is(condition.getClassId())
                    .and("students.studentId").is(condition.getStudent().getStudentId()));
            Update update = Update.update("students.$.name", condition.getStudent().getName());
            WriteResult result = mongoTemplate.upsert(query, update, "class");
            map.put("result", "success");
            map.put("msg", "共简单修改" + result.getN() + "条数据");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("result", "failed");

        }
        return map;
    }

}

log4j2.xml配置文件进行mongodb日志保存。mongodb配置信息应该抽取出来。由于测试先写死。

<?xml version="1.0" encoding="UTF-8"?>
<!--设置log4j2的自身log级别为warn -->
<configuration status="warn">

    <appenders>
        <console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
        </console>

        <RollingFile name="RollingFileInfo" fileName="logs/hpaasvc/info.log"
                     filePattern="${sys:user.home}/logs/hpaasvc/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
            <Filters>
                <ThresholdFilter level="INFO"/>
                <ThresholdFilter level="WARN" onMatch="DENY"
                                 onMismatch="NEUTRAL"/>
            </Filters>
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
        </RollingFile>

        <RollingFile name="RollingFileWarn" fileName="logs/hpaasvc/warn.log"
                     filePattern="${sys:user.home}/logs/hpaasvc/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
            <Filters>
                <ThresholdFilter level="WARN"/>
                <ThresholdFilter level="ERROR" onMatch="DENY"
                                 onMismatch="NEUTRAL"/>
            </Filters>
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
        </RollingFile>

        <RollingFile name="RollingFileError" fileName="logs/hpaasvc/error.log"
                     filePattern="${sys:user.home}/logs/hpaasvc/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="ERROR"/>
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
        </RollingFile>

        <!-- 配置mongdb appender -->
        <NoSql name="mongoAppender">
            <MongoDb databaseName="mongoTest" userName="mongoTest" password="root" collectionName="logs" server="127.0.0.1" port="27017"/>
        </NoSql>
    </appenders>

    <loggers>
        <!--过滤掉spring和hibernate的一些无用的debug信息 -->
        <logger name="org.springframework" level="INFO">
        </logger>
        <logger name="org.hibernate" level="INFO">
        </logger>

        <root level="info">
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFileInfo"/>
            <appender-ref ref="RollingFileWarn"/>
            <appender-ref ref="RollingFileError"/>
            <!-- 输出日志到mongodb -->
            <appender-ref ref="mongoAppender"/>
        </root>

    </loggers>

</configuration>

配置完毕启动项目,查看Mongodb数据库是否有日志信息
这里写图片描述
这里写图片描述

多数据源配置

参考https://blog.csdn.net/a123demi/article/details/78239251

以上说明的项目源码:https://github.com/lxwjq/mongodb-demo

展开阅读全文

没有更多推荐了,返回首页