MongoDBSpring-Data-MongoDB详细的操作手册增删改查

48次阅读

共计 8012 个字符,预计需要花费 21 分钟才能阅读完成。

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 实例配置:

@Configuration
public 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 类进行增删改查

@Service
public 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 笔记】一起学习, 每天会分享干货,还有学习视频领取!

正文完
 0