SpringBoot整合MongoDB开发记录

在控制台输出nosql的日志

#打印mongodb日志
logging.level.org.springframework.data.mongodb.core= DEBUG

查询抛ConverterNotFoundException异常

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.util.Date] to type [java.sql.Timestamp]

解决方法

  1. 自定义转换器
package com.zx.mongoconfig;
import org.springframework.core.convert.converter.Converter;
import java.sql.Timestamp;
import java.util.Date;

public class TimestampConverter implements Converter<Date, Timestamp> {

    @Override
    public Timestamp convert(Date date) {
        if (date != null) {
            return new Timestamp(date.getTime());
        }
        return null;
    }

}
  1. 配置MongoTemplate
	@Bean
    @Primary
    public MongoTemplate template(MappingMongoConverter mappingMongoConverter) {
        return new MongoTemplate(factory(), mappingMongoConverter);
    }
    @Bean
    public MappingMongoConverter mappingMongoConverter(MongoDbFactory mongoDbFactory, BeanFactory beanFactory, CustomConversions customConversions) {
        DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory);
        MongoMappingContext mongoMappingContext = new MongoMappingContext();
        MappingMongoConverter mappingMongoConverter = new MappingMongoConverter(dbRefResolver, mongoMappingContext);
        mappingMongoConverter.setCustomConversions(beanFactory.getBean(CustomConversions.class));
        mappingMongoConverter.setTypeMapper(new DefaultMongoTypeMapper(null));//去掉默认mapper添加的_class
        mappingMongoConverter.setCustomConversions(customConversions);//添加自定义的转换器
        return mappingMongoConverter;
    }
    @Bean
    public CustomConversions customConversions() {
        List list = new ArrayList();
        list.add(new TimestampConverter());
        return new CustomConversions(list);
    }

CRUD操作

常用方法

mongoTemplate.findAll(Student.class): //查询Student文档的全部数据
mongoTemplate.findById(<id>, Student.class): //查询Student文档id为id的数据
mongoTemplate.find(query, Student.class);: //根据query内的查询条件查询
mongoTemplate.upsert(query, update, Student.class): //修改
mongoTemplate.remove(query, Student.class): //删除
mongoTemplate.insert(student): //新增

若字段值为null,则新增操作不会入库

Query对象

  1. 创建一个query对象(用来封装所有条件对象),再创建一个criteria对象(用来构建条件)
  2. 精准条件:criteria.and(“key”).is(“条件”)
    模糊条件:criteria.and(“key”).regex(“条件”)
  3. 封装条件:query.addCriteria(criteria)
  4. 大于(创建新的criteria):Criteria gt = Criteria.where(“key”).gt(“条件”)
    小于(创建新的criteria):Criteria lt = Criteria.where(“key”).lt(“条件”)
  5. Query.addCriteria(new Criteria().andOperator(gt,lt));
  6. 一个query中只能有一个andOperator()。其参数也可以是Criteria数组。
  7. 排序 :query.with(new Sort(Sort.Direction.ASC, “age”). and(new Sort(Sort.Direction.DESC, “date”)))

多条件分页查询

1、使用limit和skip进行分页查询

//模糊查询
String regex = String.format("%s%s%s", "^.*", username, ".*$");
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Query query = new Query(Criteria.where("formid").is(formid)
						.and("name").regex(pattern));
//排序
query.with(new Sort(new Sort.Order(Sort.Direction.DESC, "zxitime"), new Sort.Order(Sort.Direction.DESC, "zxscore")));
//分页
query.skip((pageNum-1)*pageSize).limit(pageSize);
List<FormDataEntity> datas = this.mongoTemplate.find(query, FormDataEntity.class, CollectionName.FORM_DATA);

通过skip和limit方法可以简单的实现分页操作,但是如果数据量特别巨大的时候,会出现性能的问题,不建议使用!

2、通过原生的方法实现条件查询、分页和排序

public Page<User> getPageByOriginalFunction(int age,int pageNUmber,int pageSize){
    //查询条件,可以传递多个查询条件
    User user = new User();
    user.setAge(age);
    Example<User> example = Example.of(user);
    //分页条件
    //Pageable pageable = new PageRequest(pageNUmber,pageSize);
    Pageable pageable = PageRequest.of(pageNUmber,pageSize);
    return userRepository.findAll(example,pageable);
}
//查询结果
{
  "content": [
    {
      "id": "5cfb69ee4332ce07b864d12e",
      "name": "lsr",
      "pwd": "123456",
      "age": 18
    }
  ],
  "pageable": {
    "sort": {
      "sorted": false,
      "unsorted": true
    },
    "offset": 0,
    "pageSize": 2,
    "pageNumber": 0,
    "unpaged": false,
    "paged": true
  },
  "last": true,
  "totalPages": 1,
  "totalElements": 1,
  "number": 0,
  "size": 2,
  "sort": {
    "sorted": false,
    "unsorted": true
  },
  "first": true,
  "numberOfElements": 1
}

3、通过实现Pageable接口

  1. 创建自定义分页类,实现Pageable接口
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import javax.validation.constraints.Min;

@NoArgsConstructor
@AllArgsConstructor
public class SpringDataPageAble implements Pageable {

    @Min(1)
    private Integer pageNumber = 1;
    @Min(1)
    private Integer pageSize = 10;
    private Sort sort;

    public void setSort(Sort sort) {
        this.sort = sort;
    }

    // 当前页面
    @Override
    public int getPageNumber() {
        return this.pageNumber;
    }

    // 每一页显示的条数
    @Override
    public int getPageSize() {
        return getPagesize();
    }

    // 第二页所需要增加的数量
    @Override
    public long getOffset() {
        return (getPageNumber() - 1) * getPagesize();
    }

    @Override
    public Sort getSort() {
        return sort;
    }

    public void setPagenumber(Integer pagenumber) {
        this.pageNumber = pageNumber;
    }

    public Integer getPagesize() {
        return this.pageSize;
    }

    public void setPagesize(Integer pagesize) {
        this.pageSize = pagesize;
    }

    @Override
    public Pageable next() {
        return null;
    }

    @Override
    public Pageable previousOrFirst() {
        return null;
    }

    @Override
    public Pageable first() {
        return null;
    }

    @Override
    public boolean hasPrevious() {
        return false;
    }
}
  1. 在repository层定义分页方法
import com.tedu.huawei.entity.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

@Repository //注意MongoRepository后面接的泛型<User, String>第一个为实体类,第二个为主键ID
public interface UserRepository extends MongoRepository<User,String> {
    Page<User> getUserByPageAble(int age, Pageable pageAble);
}
  1. service层调用方法
public Page<User> getUserByPageAble(int age, int pageNumber,int pageSize){
    SpringDataPageAble springDataPageAble = new SpringDataPageAble(pageNumber,pageSize,new Sort(Sort.Direction.ASC,"age"));
    return userRepository.getUserByPageAble(age,springDataPageAble);
}
// 查询结果
{
  "content": [
    {
      "id": "5cfb66114332ce07b864d12d",
      "name": "lsr",
      "pwd": "123456",
      "age": 18
    },
    {
      "id": "5cfb85084332ce4ffca97907",
      "name": "panzi",
      "pwd": "654321",
      "age": 24
    }
  ],
  "pageable": {
    "pageNumber": 1,
    "pageSize": 2,
    "sort": {
      "sorted": true,
      "unsorted": false
    },
    "offset": 0,
    "pagesize": 2,
    "unpaged": false,
    "paged": true
  },
  "last": true,
  "totalPages": 1,
  "totalElements": 2,
  "number": 1,
  "size": 2,
  "sort": {
    "sorted": true,
    "unsorted": false
  },
  "first": false,
  "numberOfElements": 2
}

4、总结

第一种方式实现简单方便,但是不适用于大数据量。第二种分页是原生的方法,不需要做额外的处理,但是查询条件单一,不能设置大于等于或者在某某之间,以及模糊查询有很大的限制。第三种方式实现也很简单,但是更加开放和使用性能好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值