虚拟机安装MongoDB请参看《CentOS7安装MongoDB4》

我使用的IDE是STS4,大家按照自己的习惯选择即可。

关键是pom.xml要加入:

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

在application.properties中加入:

spring.data.mongodb.uri=mongodb://用户名:密码@IP:PORT/数据库

实体类

@Document(collection  = "test_goods")publicclass GoodsEntity implements Serializable {    privatestaticfinallongserialVersionUID = -805486477824888750L;    @Id    private String id;    private String goodsName;    privatelongcategoryId;    privateintgoodsStatus;    private String labels;//省略get、set方法}

其他都不解释了,一看就懂,这里要注意id这个字段。

如上配置,加上注解@Id的情况下,我们新建一条Document的时候,不需额外设置,会自动生成一个如下图的主键:

这是一个名为”_id”的ObjectId类型的主键,12个字节的BSON类型字符串。

4字节是UNIX时间戳,3字节表示MongoDB服务器,2字节是生成ID的进程,3字节是随机数。

这么做的好处是对分布式友好。并且,因为id中包含时间戳,天然的就带上了创建时间。我们可以通过

ObjectId id = new ObjectId(entity.getId());System.out.println(id.getDate());

获取创建时间。

当然了,如果我们使用MongoDB是对传统DB的一个补充,在系统中还是希望将DB中的ID存入MongoDB的话,那就去除id字段的注解,处理的时候对ID字段做好设置即可。

Dao

@Componentpublicclass GoodsDao {    @Autowired    private MongoTemplate mongoTemplate;    /**     * 新建     *     * @param entity     * @return     */    public GoodsEntity add(GoodsEntity entity) {        returnmongoTemplate.save(entity);    }    /**     * 根据ID修改     *     * @param entity     * @return     */    public UpdateResult upd(GoodsEntity entity) {        Query query = new Query(Criteria.where("id").is(entity.getId()));        Update update = new Update().set("goodsName", entity.getGoodsName()).set("categoryId", entity.getCategoryId())                .set("goodsStatus", entity.getGoodsStatus()).set("labels", entity.getLabels());        returnmongoTemplate.updateFirst(query, update, GoodsEntity.class);    }    /**     * 根据ID删除     *     * @param id     * @return     */    public DeleteResult delById(longid) {        Query query = new Query(Criteria.where("id").is(id));        returnmongoTemplate.remove(query,  GoodsEntity.class);    }    /**     * 根据主键获取详情     *     * @param id     * @return     */    public GoodsEntity getById(longid) {        Query query = new Query(Criteria.where("id").is(id));        GoodsEntity entity = mongoTemplate.findOne(query, GoodsEntity.class);        returnentity;    }    /**     * 列出所有记录     *     * @return     */    public List<GoodsEntity> listAll() {        List<GoodsEntity> entities = mongoTemplate.find(new Query(), GoodsEntity.class);        returnentities;    }    /**     * 根据某字段使用正则表达式模糊查询,且分页、ID倒序     *     * @param label     * @param pageNumber     * @param pageSize     * @return     */    public List<GoodsEntity>  queryPageByLabel(String label, intpageNumber, intpageSize) {        // 完全匹配        // Pattern pattern =  Pattern.compile("^" + label + "$",        // Pattern.CASE_INSENSITIVE);        // 右匹配        // Pattern pattern =  Pattern.compile("^.*\"+label+\"$",        // Pattern.CASE_INSENSITIVE);        // 左匹配        // Pattern pattern = Pattern.compile("^\"+label+\".*$",        // Pattern.CASE_INSENSITIVE);        // 模糊匹配        Pattern pattern = Pattern.compile("^.*" + MongoDBUtils.escapeExprSpecialWord(label) + ".*$",                Pattern.CASE_INSENSITIVE);        Query query = new Query(Criteria.where("labels").regex(pattern));        // ID倒序        query.with(new Sort(Sort.Direction.DESC, "id"));        // 分页        PageRequest pageableRequest = PageRequest.of(pageNumber, pageSize);        query.with(pageableRequest);        returnmongoTemplate.find(query,  GoodsEntity.class);    }    /**     * 多查询条件,分页,ID倒序     *     * @param entity     * @param pageNumber     * @param pageSize     * @return     */    public List<GoodsEntity>  queryPage(GoodsEntity entity, intpageNumber, intpageSize) {        Criteria criteria = new Criteria();        if (!StringUtils.isEmpty(entity.getGoodsName())) {            Pattern pattern = Pattern.compile("^.*" + entity.getGoodsName() + ".*$", Pattern.CASE_INSENSITIVE);            criteria.and("goodsName").regex(pattern);        }        if (!StringUtils.isEmpty(entity.getLabels())) {            Pattern pattern = Pattern.compile("^.*" + entity.getLabels() + ".*$", Pattern.CASE_INSENSITIVE);            criteria.and("labels").regex(pattern);        }        if (entity.getCategoryId() > 0) {            criteria.and("categoryId").is(entity.getCategoryId());        }        if (entity.getGoodsStatus() > 0) {            criteria.and("goodsStatus").is(entity.getGoodsStatus());        }        Query query = new Query(criteria);        // 分页&ID倒序        PageRequest pageableRequest = PageRequest.of(pageNumber, pageSize, Sort.Direction.DESC, "id");        query.with(pageableRequest);        returnmongoTemplate.find(query,  GoodsEntity.class);    }}

个人感觉基本覆盖了大部分需求,不再对代码详细解释了。

主要是注意一下,我这次没有使用ObjectId,而是用DB的ID,所以这里的Entity的ID是long。

测试

@RunWith(SpringRunner.class)@SpringBootTestpublicclass GoodsDaoTest {    @Autowired    private GoodsDao goodsDao;    @Test    publicvoid add() {        GoodsEntity entity = new GoodsEntity();        entity.setId(3); // 如果使用ObjectId,就不需要额外处理ID字段了。        entity.setCategoryId(5);        entity.setGoodsName("测试商品E");        entity.setGoodsStatus(1);        entity.setLabels("a,b,c,*,d");        GoodsEntity newEntity = goodsDao.add(entity);        JsonFormaterUtil.printFromObj(newEntity);    }    @Test    publicvoid upd() {        GoodsEntity entity = goodsDao.getById(1);        entity.setLabels("a,b,c,d");        JsonFormaterUtil.printFromObj(goodsDao.upd(entity));    }    @Test    publicvoid del() {        JsonFormaterUtil.printFromObj(goodsDao.delById(3));    }    @Test    publicvoid getById() {        JsonFormaterUtil.printFromObj(goodsDao.getById(1));    }    @Test    publicvoid listAll() {        JsonFormaterUtil.printFromObj(goodsDao.listAll());    }    @Test    publicvoid queryByLabel() {        JsonFormaterUtil.printFromObj(goodsDao.queryPageByLabel("*", 0, 2));    }    @Test    publicvoid queryPage() {        GoodsEntity entity = new GoodsEntity();        // entity.setCategoryId(5);        entity.setGoodsName("测试商品");        // entity.setGoodsStatus(1);        // entity.setLabels("a,b,c");        JsonFormaterUtil.printFromObj(goodsDao.queryPage(entity, 0, 10));    }}

没什么好说的。

日志配置
因为我个人喜好在控制台打印出对DB操作的语句,所以对log配置进行了修改。

Spring Boot使用的是logback,在resources目录下创建logback.xml文件,内容如下:

<?xml version="1.0"  encoding="UTF-8"?><configuration debug="false">    <!--定义日志文件的存储绝对路径-->    <property name="LOG_HOME"  value="d:/" />    <!-- 控制台输出 -->    <appender name="STDOUT"        class="ch.qos.logback.core.ConsoleAppender">        <encoder            class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level  %logger{50} : %n%msg%n            </pattern>        </encoder>    </appender>    <!-- 按照每天生成日志文件 -->    <appender name="FILE"        class="ch.qos.logback.core.rolling.RollingFileAppender">        <rollingPolicy            class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">            <!--日志文件输出的文件名 -->            <FileNamePattern>${LOG_HOME}/mongodbdemo.log.%d{yyyy-MM-dd}.log            </FileNamePattern>            <!--日志文件保留天数 -->            <MaxHistory>30</MaxHistory>        </rollingPolicy>        <encoder            class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread]  %-5level %logger{50} :                %msg%n            </pattern>        </encoder>        <!--日志文件最大的大小 -->        <triggeringPolicy            class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">            <MaxFileSize>10MB</MaxFileSize>        </triggeringPolicy>    </appender>    <!-- 日志输出级别 -->    <root level="ERROR">        <appender-ref ref="STDOUT"  />        <appender-ref ref="FILE"  />    </root>    <!-- MongoDB日志输出 -->    <logger        name="org.springframework.data.mongodb.core.MongoTemplate"        level="DEBUG"  additivity="false">        <appender-ref ref="STDOUT"  />    </logger></configuration>

关键点是配置MongoDB日志输出,其中name是输出日志的类,level设置成debug,才会将执行的语句输出出来,类似:

find using query: { "goodsName"  : { "$regex" : "^.*测试商品.*$",  "$options" : "i" } } fields: Document{{}} for class:  class org.leo.mongodb.demo.entity.GoodsEntity in collection: test_goods

而加上additivity="false"是因为如果不加,上面的日志会在控制台上打印两次。

其他
通过正则表达式查询的时候,会遇上一些特殊字符(*,?等),需要转义一下,代码如下:

publicclass MongoDBUtils {    privatestaticfinal String[] fbsArr = { "\\", "$", "(", ")", "*", "+", ".", "[", "]", "?", "^", "{", "}", "|" };    /**     * regex对输入特殊字符转义     *     * @param keyword     * @return     */    publicstatic String escapeExprSpecialWord(String keyword) {        if (!StringUtils.isEmpty(keyword)) {            for (String key : fbsArr) {                if (keyword.contains(key)) {                    keyword = keyword.replace(key, "\\" + key);                }            }        }        returnkeyword;    }}

索引:

db.getCollection("test_goods").createIndex({  "categoryId": 1 }, { "name":  "idx_goods_categoryid" })

为categoryId创建索引,其中{ "categoryId": 1 }的1,代表按升序创建,-1代表降序。

创建复合索引,如下:

db.getCollection("test_goods").createIndex({ "categoryId": 1,  "goodsStatus": -1 })

设置唯一索引,如下:

db.getCollection("test_goods").createIndex({  "categoryId": 1}, {  "unique": true })
©著作权归作者所有:来自51CTO博客作者mb5fe559d8b9ae4的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. Android开发指南中文版(七)Content Providers
  2. Android逆向之旅---SO(ELF)文件格式详解
  3. android listview 连续调用 getview问题分析及解决。
  4. Android 日志保存到本地---CscSDK
  5. Android安卓开发集成微信第三方扫描二维码登录-超级无敌具详细
  6. 服务器日志现 Android 4.2 传将添多项新特性
  7. 解析URL,获取其参数值(总结一次与H5交互用到的)

随机推荐

  1. android 选择本地图片并预览
  2. Android的OpenGL学习笔记(1)
  3. Android 条码扫描程序源码
  4. android中将中文以粗体显示
  5. Android程序横竖屏切换
  6. 对比onSaveInstanceState和onRestoreInst
  7. Android(安卓)getIdentifier获取资源ID
  8. 关于LinearLayout布局中,子控件平分宽度
  9. android获取3G或wifi流量信息
  10. Android使用selector改变和文本框文字的