github:https://github.com/Ccww-lx/Sp...
模块:spring-boot-base-mongodb

  在NoSQL盛行的时代,App很大可能会涉及到MongoDB数据库的使用,而也必须学会在Spring boot使用Spring Data连接MongoDB进行数据增删改查操作,如下为详细的操作手册。

1. 依赖

直接导入spring-data-mongodb包或者使用Spring Boot starter

<dependencies>  <!-- other dependency elements omitted -->  <dependency>    <groupId>org.springframework.data</groupId>    <artifactId>spring-data-mongodb</artifactId>    <version>2.2.0.RELEASE</version>  </dependency></dependencies><!--spring 框架使用最新的 --><spring.framework.version>5.2.0.RELEASE</spring.framework.version><!--用一即可--><!--使用Spring Boot starter--> <dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-data-mongodb</artifactId></dependency>

2. 属性文件application.properties

#mongodb连接地址,集群用“;”隔开spring.mongo.mongoDatabaseAddress=10.110.112.165:27092;10.110.112.166:27092#mongo数据名spring.mongo.dbname=mongodb#mongo用户spring.mongo.username=mongodbopr#mongo密码spring.mongo.password=123456#mongo最大连接数spring.mongo.connectionsPerHost=50

3. mongodb 配置

注册Mongo实例配置:

@Configurationpublic class MongodbConfig {    public static final String COMMA = ";";    public static final String COLON = ":";        @Value("${spring.mongo.mongoDatabaseAddress}")    private String mongoDatabaseAddress;        @Value("${spring.mongo.username}")    private String username;    @Value("${spring.mongo.dbname}")    private String dbname;        @Value("${spring.mongo.password}")    private String password;        @Value("${spring.mongo.connectionsPerHost}")    private String connectionsPerHost;        /**     * 获取mongodb的地址     *     * @return     */    private List<ServerAddress> getMongoDbAddress() {        List<ServerAddress> serverAddrList = new ArrayList<ServerAddress>();        //如果有多个服务器的话        if (this.mongoDatabaseAddress.indexOf(COMMA) > 0) {            String[] addressArrays = mongoDatabaseAddress.split(COMMA);            String[] hostPort;            for (String address : addressArrays) {                hostPort = address.split(COLON);                ServerAddress serverAdress = new ServerAddress(hostPort[0], Integer.valueOf(hostPort[1]));                serverAddrList.add(serverAdress);            }        } else {            String[] hostPort = mongoDatabaseAddress.split(COLON);            ServerAddress serverAdress = new ServerAddress(hostPort[0], Integer.valueOf(hostPort[1]));            serverAddrList.add(serverAdress);        }        return serverAddrList;    }    /**     * 设置连接参数     */    private MongoClientOptions getMongoClientOptions() {        MongoClientOptions.Builder builder = MongoClientOptions.builder();        // todo 添加其他参数配置        //最大连接数        builder.connectionsPerHost(Integer.valueOf(connectionsPerHost));        MongoClientOptions options = builder.readPreference(ReadPreference.nearest()).build();        return options;    }    /**     *     * @return     */    @Bean    public MongoClient mongoClient() {        //使用数据库名、用户名密码登录        MongoCredential credential = MongoCredential.createCredential(username, dbname, password.toCharArray());        //创建Mongo客户端        return new MongoClient(getMongoDbAddress(), credential, getMongoClientOptions());    }    /**     * 注册mongodb操作类     * @param mongoClient     * @return     */    @Bean    @ConditionalOnClass(MongoClient.class)    public MongoTemplate mongoTemplate(MongoClient mongoClient) {        MongoTemplate mongoTemplate = new MongoTemplate(new SimpleMongoDbFactory(mongoClient, dbname));        return mongoTemplate;    }}

4. mongodb操作

使用MongoTemplate类进行增删改查

@Servicepublic class MongodbService {    @Autowired    private MongoTemplate mongoTemplate;    /**     * 新增文档     *     * @param userDTO     * @return     */    public UserDTO insert(UserDTO userDTO) {        //insert方法并不提供级联类的保存,所以级联类需要先自己先保存        return mongoTemplate.insert(userDTO);    }    public UserDTO save(UserDTO userDTO) {        Sort sort = new Sort(Sort.Direction.DESC, "name");        userDTO = mongoTemplate.findOne(Query.query(Criteria.where("")).with(sort), UserDTO.class);        return mongoTemplate.save(userDTO);    }    /**     * 删除文档     * NOTE:remove方法不支持级联删除所以要单独删除子数据     * @param name     */    public void remove(String name) {        //根据名字查询数据并删除        UserDTO userDTO = mongoTemplate.findOne(Query.query(Criteria.where("name").is(name)), UserDTO.class);        //remove方法不支持级联删除所以要单独删除子数据        List<AddressDTO> addressList = userDTO.getAddressList();        for (AddressDTO addressDTO : addressList) {            mongoTemplate.remove(addressDTO);        }        //删除主数据        mongoTemplate.remove(userDTO);    }    /**     * 更新文档     * @param userDTO     */    public void update(UserDTO userDTO) {        mongoTemplate.updateFirst(Query.query(Criteria.where("name").is(userDTO.getName())), Update.update("age", userDTO.getAge()), UserDTO.class);    }    /**     * 查询文档     * @param name     */    public void find(String name) {        Sort sort = new Sort(Sort.Direction.DESC, "name");        List<UserDTO> userDTOS = mongoTemplate.find(Query.query(Criteria.where("name").is(name)), UserDTO.class);        //基于sort排序使用findOne查询最新一条记录        UserDTO userDTO = mongoTemplate.findOne(Query.query(Criteria.where("name").is(name)).with(sort), UserDTO.class);        //模糊查询        List<UserDTO> userDTOList = mongoTemplate.find(Query.query(Criteria.where("name").is(name).regex(name)).with(sort), UserDTO.class);        //分页查询        Pageable pageable = PageRequest.of(3, 20, sort);        List<UserDTO> userDTOPageableList = mongoTemplate.find(Query.query(Criteria.where("name").is(name)).with(pageable), UserDTO.class);        //总数        long conut = mongoTemplate.count(Query.query(Criteria.where("name").is(name)), UserDTO.class);        Page<UserDTO> page = new PageImpl(userDTOPageableList, pageable, conut);    }}

NOTE:
  在开发中,如果从任何MongoDB操作返回的com.mongodb.WriteResult包含错误,则可以方便地记录或引发异常。 通常,在开发过程中很容易忘记执行此操作,然后最终得到一个看似运行成功的App,但实际上该数据库操作发生异常,没执行成功。 可以将MongoTemplateWriteResultChecking属性设置为以下值之一:

  • EXCEPTION:引发Exception
  • NONE:不执行任何操作,默认值

  对于更高级的情况,可以将每个操作设置不同的WriteConcern值(用于删除,更新,插入和保存操作),则可以在MongoTemplate上配置WriteConcernResolver的策略接口。 由于MongoTemplate用于持久化POJO,因此WriteConcernResolver允许您创建一个策略,该策略可以将特定的POJO类映射到WriteConcern值。

WriteConcernResolver接口:

public interface WriteConcernResolver {  WriteConcern resolve(MongoAction action);}

自定义WriteConcernResolver接口,实现不同WriteConcern策略:

private class MyAppWriteConcernResolver implements WriteConcernResolver {  public WriteConcern resolve(MongoAction action) {    if (action.getEntityClass().getSimpleName().contains("UserDTO")) {      return WriteConcern.NONE;    } else if (action.getEntityClass().getSimpleName().contains("Metadata")) {      return WriteConcern.JOURNAL_SAFE;    }    return action.getDefaultWriteConcern();  }}

5. 常用的类以及方法解析

5.1 MongoClient、ServerAddress、MongoCredential以及MongoClientOptions

  基于ServerAddress单机或者Replica Set在使用MongoClient连接mongodb数据库注册mongo实例,在注册示例中可能要使得MongoCredential账号密码验证以及使用MongoClientOptions配置mongodb其他的参数。

MongoClient常用的构造器方法:

public MongoClient(String host){}public MongoClient(MongoClientURI uri){}public MongoClient(String host, MongoClientOptions options) {}public MongoClient(ServerAddress addr, MongoCredential credential, MongoClientOptions options){}public MongoClient(List<ServerAddress> seeds, MongoCredential credential, MongoClientOptions options){}

5.2 MongoTemplate

使用MongoTemplate结合SortCriteriaQueryUpdate以及分页Pageable类灵活地进行对mongodb数据库进行增删改查。

query方法:

//根据查询条件查询 public <T> List<T> find(Query query, Class<T> entityClass){} //根据查询条件查询返回一条记录 public <T> <T>findOne(Query query, Class<T> entityClass){} //查询该collection所有记录 public <T> List<T> findAll(Class<T> entityClass){}

insert方法:

//新增一条记录 public <T> T insert(T objectToSave){} //在collectionName中新增一条记录 public <T> T insert(T objectToSave, String collectionName) {} // public <T> T save(T objectToSave){}

remove方法:

//根据Object删除 public DeleteResult remove(Object object) {} //根据查询条件进行删除 public DeleteResult remove(Query query, Class<?> entityClass){}

update方法:

 // public UpdateResult upsert(Query query, Update update, Class<?> entityClass) {} //更新查询出来的第一条记录 public UpdateResult updateFirst(Query query, Update update, String collectionName) {}

5.3 Sort

Sort查询排序类。Sort类常用方法:

//构造方法创建一个排序。direction为排序方向的枚举类型,properties为排序字段数组Sort(Sort.Direction direction, String... properties)//多个排序条件链接and(Sort sort)//返回升序排列对象ascending()    //返回降序排列对象descending()    

5.4 Criteria

Criteria查询条件类,类似于SQL的where,常用方法:

//声明定义查询条件,且为静态方法where(String key)//与操作and(String key)//正则表达式,即可为模糊查询regex(String re)//包含in(Object... o)    //大于gt(Object o)//大于等于gte(Object o)//等于is(Object o)//小于lt(Object o)//小于等于lte(Object o) //非not()//创建与操作andOperator(Criteria... criteria)    

5.5 Query

Query查询对象,具有查询的全部信息,其中包括筛选条件、排序、返回数量等。常用的方法:

//定义查询对象,静态方法query(CriteriaDefinition criteriaDefinition)//在本次查询添加一个CriteriaDefinition查询条件addCriteria(CriteriaDefinition criteriaDefinition)//添加一个Sort排序对象with(Sort sort)//添加一个Pageable分页对象、通常情况下,分页和排序一起使用。with(Pageable pageable)

详细接口信息可查看【MogoDB API官方文档】

6.常用注解

注解解析
@Id用于标记id字段,没有标记此字段的实体也会自动生成id字段,但是我们无法通过实体来获取id。id建议使用ObjectId类型来创建
@Document用于标记此实体类是mongodb集合映射类
@DBRef用于指定与其他集合的级联关系,但是需要注意的是并不会自动创建级联集合
@Indexed用于标记为某一字段创建索引
@CompoundIndex用于创建复合索引
@TextIndexed:用于标记为某一字段创建全文索引
@Language指定documen语言
@Transient:被该注解标注的,将不会被录入到数据库中。只作为普通的javaBean属性
@Field:用于指定某一个字段映射到数据库中的名称



最后可关注公众号:【Ccww笔记】 一起学习,每天会分享干货,还有学习视频领取!