MongoTemplate 基础使用帮助手册
前言
MongoDB 是一种流行的 NoSQL 数据库,适合存储大量的非结构化数据。MongoTemplate 是 Spring Data MongoDB 中的一个核心组件,它提供了一组丰富的 API 来与 MongoDB 进行交互。它封装了许多常见的数据库操作,使开发者能够轻松执行 CRUD 操作、处理复杂查询和聚合等。本文将详细介绍 MongoTemplate 的基本用法,包含语法介绍和具体的使用示例。
一、初识 MongoTemplate
1.1 Spring Data MongoDB 简介
Spring Data MongoDB 是 Spring Data 项目的一部分,提供了与 MongoDB 文档数据库的集成。Spring Data MongoDB 的关键功能是一个以 POJO 为中心的模型,用于与 MongoDB 数据集合交互,并轻松地编写一个存储库风格的数据访问层。在 Spring Boot 项目中使用 MongoDB,首先需要引入 MongoDB 的依赖,通过在 POM 文件中引入 MongoDB 的依赖坐标,即可将操作 MongoDB 的类库整合入 SpringBoot 项目当中,相关依赖如下:
<!-- springboot 整合 mongodb -->
<dependency> <groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId><version>x.y.z</version>
</dependency>
1.2 MongoTemplate 简介
MongoTemplate 类位于 org.springframework.data.mongodb.core 包中,是 Spring 支持 MongoDB 的高级抽象类,为与 MongoDB 数据库交互提供了丰富的功能集。其封装了 MongoClient,提供了一个更高层次的模板方法 API 来简化 MongoDB 的操作。通过相对简单的方法来执行创建、更新、删除和查询 MongoDB 等操作,同时集成了 Spring 的转换和异常处理机制。使用 MongoTemplate,不需要关心低层次的数据库连接和错误处理。而且 MongoTemplate 支持将 Java 对象映射到 MongoDB 文档,并提供了一组方法,用于在 Java 对象和 MongoDB 文档之间进行转换,这样可以方便地操作和管理数据。
【注意】MongoTemplate 是线程安全的,一旦配置好就可以在多个实例中重复使用(多线程环境中)。
我们先看看 MongoTemplate 的构造方法,它有几个重载的构造函数,如下所示:
/*** 根据 MongoClient 对象和要对其进行操作的默认数据库名称去实例化 MongoTemplate。*/
public MongoTemplate(MongoClient mongoClient, String databaseName) {}
/*** 根据 MongoDatabaseFactory 对象实例化 MongoTemplate,^ MongoDatabaseFactory 封装了 MongoClient 对象、数据库名称、用户名和密码等信息。*/
public MongoTemplate(MongoDatabaseFactory mongoDbFactory) {}
/*** 用于对象和文档映射的 MongoConverter 接口实现去实例化 MongoTemplate*/
public MongoTemplate(MongoDatabaseFactory mongoDbFactory, MongoConverter mongoConverter) {
}
1.3 添加配置
引入依赖之后,需要在配置文件中添加 MongoDB 的连接信息,如同使用 MySQL 一样需要给出它的连接信息。可以通过配置文件,定义其配置参数,具体参数有如下(将其对应参数写在 application.properties 或者 application.yml 即可):
参数 | 描述 |
---|---|
spring.data.mongodb.additional-hosts | 验证的数据库 |
spring.data.mongodb.authentication-database | 验证的数据库 |
spring.data.mongodb.auto-index-creation | 是否自动创建索引 |
spring.data.mongodb.database | 指定要使用的数据库名称,初始化数据的时候,会自动创建。 |
spring.data.mongodb.field-naming-strategy | 字段命名策略 |
spring.data.mongodb.gridfs.bucket | |
spring.data.mongodb.gridfs.database | |
spring.data.mongodb.host | 设置 MongoDB 主机名,默认为 localhost。 |
spring.data.mongodb.password | MongoDB数据库密码,根据实际情况填写即可 |
spring.data.mongodb.port | 设置 MongoDB 端口号,默认为 27017。 |
spring.data.mongodb.repositories.type | |
spring.data.mongodb.ssl.bundle | |
spring.data.mongodb.ssl.enabled | |
spring.data.mongodb.uri | 定义完整的 MongoDB URI 地址,通常优先于其他单独的属性 |
spring.data.mongodb.username | MongoDB数据库用户,根据实际情况填写即可 |
spring.data.mongodb.uuid-representation |
1.4 定义对应集合的实体类
操作 MySQL 时,我们会将 MySQL 的表在项目中定义一个对应的实体类,操作 MongoDB 的集合也需要定义一个对应的实体类,这里定义一个 SysUser 的实体类来进行操作。
@Data
@Builder
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class SysUser {@Idprivate String id;@Field("name")private String name;private Integer age;private String gender;
}
注解名称 | 作用对象 | 功能 |
---|---|---|
@Document | 实体类 | 表明这是一个 MongoDB 的文档集合,相当于 MySQL 的数据表,默认为实体类名称。 |
@CompoundIndex | 实体类 | 复合索引 |
@Id | 字段 | 用于实体类中的成员变量,表示主键标识,会将该字段与 MongoDB 生成的 _id 字段进行对应。 |
@Field | 字段 | 用于实体类中的成员变量,表示 MongoDB 文档集合中的字段,其值对应集合的字段名称。 |
@Indexed | 字段 | 声明该字段需要加索引,加索引后以该字段为条件检索将大大提高速度 |
@Transient | 字段 | 表示该字段不在 mongo 中存储,既忽略该字段 |
【注意】就个人而言,不太推荐使用 @Document 来定义实体类,由于 Mongo 的特性,在我们保存数据时,若是集合中没有某些字段,Mongo 会自动创建,而且处于业务需求,可能存在同样的数据结构、不同内容需要存放于不同的集合中,我们只需创建一个实体类,然后指定不同集合存储数据即可。
1.5 注入 MongoTemplate
MongoTemplate 基于 Spring 容器提供了一组对 MongoDB 操作的基本方法,只要将 MongoTemplate 注入到需要使用的类中,即可直接使用。通过 @Autowired 将 MongoTemplate 进行注入,如下所示:
@Resource
private MongoTemplate mongoTemplate;
二、核心对象
MongoDB 支持非常强大的查询功能,使用 Query 和 Criteria 对象,可以构建复杂的查询条件并执行查询。Criteria 是 MongoTemplate 的标准查询接口,它可以把多个查询条件通过链式操作进行拼接,然后通过 Query 可以构建查询语句。
2.1 Query
Query 表示条件、排序等的 MongoDB 查询对象,用来封装所有的查询条件。我们先看看 Query 的构造方法,如下所示:
public Query() {
}/*** 通过注入一个 CriteriaDefinition 条件对象获得 Query 查询对象* 在简单查询时使用此方法将非常的方便*/
public Query(CriteriaDefinition criteriaDefinition) {this.addCriteria(criteriaDefinition);
}
Query 对象创建也很简单,如下所示:
// 用来封装所有条件的对象
Query query = new Query();
// 或者
Query query = new Query(criteria);
Query 类有一些额外的方法,可以为查询提供选项:
方法 | 简要说明 |
---|---|
Query addCriteria(CriteriaDefinition criteriaDefinition) | 用于向查询添加其他查询条件 |
Field fields() | 用于定义要包含在查询结果中的字段 |
Query skip(long skip) | 跳过文档的数量,可以与 limit 配合使用实现分页效果。 |
Query limit(int limit) | 用于限制将返回文档结果的数量(大小) |
Query with(Pageable pageable) | 添加一个分页对象 |
Query with(Sort sort) | 用于为结果提供排序定义 |
@Test
public void complexQuery() {Query pageQuery=query.with(PageRequest.of(pageIndex - 1, pageSize)).with(Sort.by(Sort.Direction.DESC,"classNo"));// 根据单个条件查询集合中的文档数据,并按指定字段进行排序与限制指定数目Query query = new Query(Criteria.where("userName").is(userName)).with(Sort.by("createTime")).limit(2).skip(1);
}
2.2 Criteria
用于封装所有的查询条件对象,相当于 SQL 的 where。它遵循流畅的 API 风格,可以轻松地将多个条件链接在一起。我们先看看 Criteria 的构造方法,如下所示:
public Criteria() {}public Criteria(String key) {}protected Criteria(List<Criteria> criteriaChain, String key) {}
Criteria 类提供以下方法,所有这些方法都对应于 MongoDB 中的操作符:
方法 | Mongodb | 简要说明 |
---|---|---|
Criteria where(string key) | $expr | 静态方法,用它可以很方便的定义查询条件 |
Criteria and(String key) | $and | |
Criteria all(Object value) | 匹配所有指定元素的文档。 | |
Criteria exists(boolean value) | $exists | 查询存在指定字段的文档。 |
Criteria gt(Object value) | $gt | 范围查询,匹配大于(>)指定值的文档 |
Criteria gte(Object value) | $gte | 范围查询,匹配大于等于(>=)指定值的文档。 |
Criteria in(Object… values) | $in | 包含 |
Criteria is(Object value) | $is | 精确查询 |
Criteria isNull() | ||
Criteria isNullValue() | ||
Criteria lt(Object value) | $lt | 范围查询,匹配小于(<)指定值的文档。 |
Criteria lte(Object value) | $lte | 范围查询,匹配小于等于(<=)指定值的文档。 |
Criteria mod(Number value, Number remainder) | 取余条件查询。 | |
Criteria ne(Object value) | $ne | 匹配不等于(≠)指定值的文档。 |
Criteria nin(Object… values) | $nin | |
Criteria not(Object value) | $not | 查询与表达式不匹配的文档。 |
regex(String re) | $regex | 模糊条件。正则表达式,用于模式匹配 |
Criteria size(int size) | $size | 匹配数组长度为指定大小的文档。 |
Criteria andOperator(Criteria… criteria) | $and | 创建与操作 |
Criteria orOperator(Criteria… criteria) | $or | 创建或操作 |
Criteria norOperator(Criteria… criteria) | $nor |
@Test
public void complexQuery() {/*** 根据【AND】关联多个查询条件,查询集合中的文档数据*/Criteria nameCriteria = Criteria.where("name").is("成龙");Criteria ageCriteria = Criteria.where("age").gte(30);Criteria orOperatorCriteria = new Criteria().orOperator(nameCriteria, ageCriteria);/*** 根据【OR】关联多个查询条件,查询集合中的文档数据*/Criteria genderCriteria = Criteria.where("gender").is("女");Criteria andOperatorCriteria = new Criteria().andOperator(genderCriteria);Query query = new Query();query.addCriteria(andOperatorCriteria);query.addCriteria(orOperatorCriteria);
}
这里的写法类似于 SQL 中的 where ( name = "成龙" or age >= 30 ) and gender=“女”
,总体来看,一个 Criteria 实例,就是一个查询条件。我们可以通过 or、and 操作来不断的组合生成一个新的Criteria实例,也就是一个新的查询条件 ,并且可以以此查询条件继续组合生成更高级的Criteria,以此不断的类推。
2.3 Update
用于轻松构建 MongoDB 更新子句的类,位于 org.springframework.data.mongodb.core.query
包中。其常用方法如下表所示:
方法 | 简要说明 |
---|---|
Update update(String key,Object value) | 更新字段 |
Update addToSet(String key) | 用来添加值到一个数组中去,如果数组中已经存在该值,那么将不会有任何的操作。 |
Update currentDate(String key) | 用来设置字段的值为当前时间 |
Update currentTimestamp(String key) | |
void inc(String key) | |
Update inc(String key, Number inc) | 用来对字段的值进行增加和减少指定的值 |
Update max(String key, Object value) | 用来判断字段的值是否比指定的值大,如果是,则将指定的值设置给字段。 |
Update min(String key, Object value) | 用来判断字段的值是否比指定的值小,如果是,则将指定的值设置给字段。 |
Update multiply(String key, Number multiplier) | 用来对字段的值乘以一个数字 |
Update pop(String key, Position pos) | 用来从字段数组中的头部和尾部删除一个元素 |
Update pull(String key, @Nullable Object value) | 用来从字段数组值中删除所有指定的值 |
Update pullAll(String key, Object[] values) | 用来从字段数组值中删除所有指定的值 |
Update push(String key, Object value) | 用来向已有的数组末尾加入一个元素。 要是不存在,就会创建一个新的。如果已存在,会造成元素的重复。所以在使用的时候,要确保该元素不存在。 |
Update rename(String oldName, String newName) | 用来对字段进行重命名 |
Update set(String key, Object value) | 将字段的值设置为指定的值,如果该字段不存在,将添加一个具有指定值的新字段。 |
Update setOnInsert(String key, Object value) | 设置字段值,字段不存在则新建字段 |
Update unset(String key) | 用来删除指定的字段。 |
三、集合操作
集合是 MongoDB 中存储文档的容器,类似于关系型数据库中的表。它是数据库中的一个逻辑分组,用于组织和管理相关的文档。一个数据库可以包含多个集合,每个集合可以包含零个或多个文档。集合中的文档可以具有不同的结构,即它们可以包含不同的字段和数据类型,这给 MongoDB 带来了极大的灵活性,但都遵循 MongoDB 的文档格式规范(BSON格式)。
3.1 新增操作
在 MongoDB 中,集合是不需要手动创建,当创建文档时,如果文档所在的集合不存在,就会自动创建集合。MongoDB 会在第一次插入文档时自动创建集合,但也可以显式创建集合,以便进行自定义配置,如下所示:
MongoCollection<Document> createCollection(Class entityClass);
MongoCollection<Document> createCollection(Class entityClass, CollectionOptions collectionOptions);
MongoCollection<Document> createCollection(String collectionName);
MongoCollection<Document> createCollection(String collectionName CollectionOptions collectionOptions);
CollectionOptions 指定了创建集合要用的一些参数:
public class CollectionOptions {// 指定集合中的最大文档数量。当达到最大值,会自动删除最早存入的文档。private Long maxDocuments;// 指定整个集合的容量。当达到最大值,会将旧文档移除。private Long size;// 是否创建固定大小集合。当达到最大值时,会自动覆盖最早的文档。当该值为 true 时,必须指定 size 参数。private Boolean capped;// 用于文档验证的表达式private Collation collation;// 用来设置自定义规则,对集合中的文档进行验证。private ValidationOptions validationOptions;// 用来创建时序集合的private TimeSeriesOptions timeSeriesOptions;
}
【注意】在 MongoDB 中,自动创建集合简单快速、适合快速原型开发,不需要事先定义集合结构。但可能会导致数据结构不一致(尤其在团队协作中),而且自动创建的集合无法预设索引或其他选项。特别说明一下,若插入的集合已经存在,则会抛出异常。
3.2 查询操作
方法 | 简要说明 |
---|---|
String getCollectionName(entityClass) | 可获取到entityClass实体类所对应的集合名称 |
MongoCollection<Document> getCollection(collectionName) | 返回的是基本的Driver集合对象,即DBCollection类型 |
Set<String> getCollectionNames() | 返回一个String列表,包含所有集合名称 |
boolean collectionExists(entityClass) boolean collectionExists(String collectionName) | 判断集合存在 |
3.3 删除操作
删除集合是另一项常见的操作,MongoDB 提供了简单的命令来执行此操作。删除集合将删除集合中的所有文档,并释放相关资源。
方法 | 简要说明 |
---|---|
dropCollection(entityClass) | 删除集合 |
dropCollection(collectionName) |
【注意】一旦集合被删除,所有文档将无法恢复。务必谨慎操作,尤其是在生产环境中,确保有足够的权限进行集合的创建和删除操作。通常,只有管理员用户或具有特定权限的用户才能执行这些操作。
四、文档的 CRUD 操作
文档是 MongoDB 中的最小数据单元,以键值对的形式组织,类似于 JSON 对象(实际上是 BSON,即 Binary JSON)。MongoTemplate 提供了一系列方便的方法来执行基本的 CRUD 操作。CRUD 是 MongoDB 中的核心操作,包含插入、读取、更新和删除等,以下将逐一讲解这些操作。
4.1 保存(插入)操作
MongoTemplate 上有几个便捷方法,如下表所示,用于保存和插入对象。Mongodb 中也像传统的关系数据库里表一样,有主键(_id)概念,用来唯一标识。当用户往 Mongodb 中插入一条新记录的时候,如果没有指定_id属性,那么 mongodb 会自动生成一个 ObjectId 类型的值,保存为 _id 的值。
方法 | 简要说明 |
---|---|
insert(T objectToSave) insert(T objectToSave, String collectionName) | |
insert(Class domainType) insert(Collection batchToSave, Class entityClass) insert(Collection batchToSave, String collectionName) | 文档插入。 若新增数据的主键已经存在,则会抛出异常提示主键重复,不保存当前数据。 |
insertAll(Collection batchToSave) | 批量插入多个文档,批量插入不用遍历,效率高 |
save(T objectToSave) save(T objectToSave, String collectionName) | 用于保存或更新操作,传递定义好的JavaBean即可,被保存的数据对象会作为返回值被返回。 通过主键 ID 进行判断,如果存在就更新,否则就插入。 |
【注意】没指定集合名称时,会取 @Document注解中的集合名称。
@SpringBootTest
public class SaveTest {@Resourceprivate MongoTemplate mongoTemplate;private final String collectionName = "SaveTest";@BeforeEachpublic void init() {// 删除集合mongoTemplate.dropCollection(collectionName);}/*** 自定义集合,插入文档*/@Testpublic void insertTest() {SysUser sysUser = new SysUser("12", "黄小飞", "女", 33);mongoTemplate.insert(sysUser, collectionName);}/*** 自定义集合,批量插入文档*/@Testpublic void insertBatchTest() {List<SysUser> userList = new ArrayList<>();userList.add(new SysUser("1", "白鹿", "女", 31));userList.add(new SysUser("2", "陈都灵", "女", 32));userList.add(new SysUser("3", "高圆圆", "女", 46));userList.add(new SysUser("4", "张含韵", "女", 36));userList.add(new SysUser("5", "李沁", "女", 35));userList.add(new SysUser("6", "胡歌", "男", 43));userList.add(new SysUser("7", "刘亦菲", "女", 38));userList.add(new SysUser("8", "成龙", "男", 71));userList.add(new SysUser("9", "杨幂", "男", 39));userList.add(new SysUser("10", "陈钰琪", "女", 33));mongoTemplate.insert(userList, collectionName);}/*** 自定义集合,存储文档,如果没有插入,否则更*/@Testpublic void saveTest() {SysUser sysUser = new SysUser("12", "黄小飞", "女", 33);mongoTemplate.save(sysUser, collectionName);}
}
【注意】使用 insert 插入文档时,如果插入数据的主键已经存在,则会抛键重复异常,不保存当前数据。而使用 save 插入文档时,如果插入数据的主键已经存在,则会更新当前数据,如果不存在则会保存当前数据。
4.2 查询操作
MongoDB 提供了灵活的查询语法,支持条件查询、复杂查询、聚合查询等。
方法 | 简要说明 |
---|---|
List find(query, entityClass) List find(query, entityClass, collectionName) | 根据查询条件查询多个文档 |
findOne(query, entityClass) findOne(query, entityClass, collectionName) | 用于查找集合中的单个文档。如果找到多个匹配的文档,它只返回第一个。 |
findById(id, entityClass) findById(id, entityClass, collectionName) | 根据ID查询文档。在添加数据时, MongoDB 会自动生成了 id,名为 _id 。 |
List findAll(className) List findAll(className, collectionName) | 查询指定集合中所有数据 |
count(query, entityClass) count(query, collectionName) count(query, entityClass, collectionName) | 查询符合条件的数量 |
findDistinct(query, field, entityClass, resultClass) findDistinct(query, field, collectionName, entityClass, resultClass) | 只能用于单个字段去重查询的方法,主要用于获取某个字段的所有不同值。 |
【注意】没指定集合名称时,会取 @Document注解中的集合名称。
@SpringBootTest
public class FindTest {@Resourceprivate MongoTemplate mongoTemplate;private final String collectionName = "FindTest";@BeforeEachpublic void init() {// 删除集合mongoTemplate.dropCollection(collectionName);List<SysUser> userList = new ArrayList<>();userList.add(new SysUser("1", "白鹿", "女", 31));userList.add(new SysUser("2", "陈都灵", "女", 32));userList.add(new SysUser("3", "高圆圆", "女", 46));userList.add(new SysUser("4", "张含韵", "女", 36));userList.add(new SysUser("5", "李沁", "女", 35));userList.add(new SysUser("6", "胡歌", "男", 43));userList.add(new SysUser("7", "刘亦菲", "女", 38));userList.add(new SysUser("8", "成龙", "男", 71));userList.add(new SysUser("9", "杨幂", "男", 39));userList.add(new SysUser("10", "陈钰琪", "女", 33));mongoTemplate.insert(userList, collectionName);}/*** 根据条件查询集合中符合条件的文档*/@Testpublic void findTest() {Query query = new Query(Criteria.where("age").gte(30).lte(40));mongoTemplate.find(query, SysUser.class, collectionName).forEach(System.out::println);}/*** 根据条件查询集合中符合条件的文档,返回第一条数据*/@Testpublic void findOneTest() {Query query = new Query(Criteria.where("gender").is("女"));SysUser sysUser = mongoTemplate.findOne(query, SysUser.class, collectionName);System.out.println("查询结果:" + sysUser);}/*** 查询集合中指定的ID文档数据*/@Testpublic void findByIdTest() {SysUser sysUser = mongoTemplate.findById("1", SysUser.class, collectionName);System.out.println(sysUser);}/*** 查询集合中的全部文档数据*/@Testpublic void findAllTest() {mongoTemplate.findAll(SysUser.class, collectionName).forEach(System.out::println);}@Testpublic void countTest() {System.out.println( mongoTemplate.count(new Query(), collectionName));}
}
4.3 更新操作
4.3.1 基本更新操作
在 MongoDB 中,更新文档的操作包括单文档更新和多文档更新,可以使用多种方法实现,常用的方法如下表所示。
方法 | 简要说明 |
---|---|
UpdateResult updateFirst(query, update, entityClass) UpdateResult updateFirst(query, update, collectionName) UpdateResult updateFirst(query, update, entityClass, collectionName) | 用于更新第一个匹配查询条件的文档 |
UpdateResult updateMulti(query, update, entityClass) UpdateResult updateMulti(query, update, collectionName) UpdateResult updateMulti(query, update, entityClass, collectionName) | 用于更新所有匹配查询条件的文档 |
UpdateResult upsert(query, update, entityClass) UpdateResult upsert(query, update, collectionName) UpdateResult upsert(query, update, entityClass, collectionName) | 进行插入或更新操作。如果文档不存在,则插入新文档,否则更新文档。 这种操作非常符合我们某些需要保证在一定条件下只能有一个文档的情况。 |
【注意】没指定集合名称时,会取 @Document注解中的集合名称。
@SpringBootTest
public class UpdateTest {@Resourceprivate MongoTemplate mongoTemplate;private final String collectionName = "UpdateTest";@BeforeEachvoid init() {mongoTemplate.dropCollection(collectionName);List<SysUser> sysUserList = new ArrayList<>();sysUserList.add(SysUser.builder().id("ID10001").name("Tom").age(34).gender("男").build());sysUserList.add(SysUser.builder().id("ID10002").name("Tony").age(23).gender("男").build());sysUserList.add(SysUser.builder().id("ID10003").name("Ross").age(44).gender("女").build());sysUserList.add(SysUser.builder().id("ID10004").name("Gloria").age(14).gender("女").build());sysUserList.add(SysUser.builder().id("ID10005").name("Linda").age(24).gender("女").build());sysUserList.add(SysUser.builder().id("ID10006").name("regina").age(26).gender("女").build());sysUserList.add(SysUser.builder().id("ID10007").name("John").age(22).gender("男").build());sysUserList.add(SysUser.builder().id("ID10008").name("Michael").age(22).gender("男").build());mongoTemplate.save(sysUserList, collectionName);}/*** 更新文档,匹配查询到的文档数据中的第一条数据*/@Testpublic void updateFirstTest() {// 更新条件Query query = new Query(Criteria.where("_id").is("ID10001"));System.out.println("更新前" + mongoTemplate.find(query, SysUser.class,collectionName));Update update = new Update();// 更新值update.set("name", "张三");update.set("sex", "男");// 更新查询满足条件的文档数据(第一条)UpdateResult updateResult = mongoTemplate.updateFirst(query, update, SysUser.class, collectionName);System.out.println(updateResult);}/*** 更新文档,匹配查询到的文档数据中的所有数据*/@Testpublic void updateMultiTest() {// 更新条件Query query = new Query(Criteria.where("age").gte(30));// 更新值Update update = Update.update("age", 33);// 更新查询满足条件的文档数据(全部)mongoTemplate.updateMulti(query, update, SysUser.class, collectionName);}@Testpublic void upsertTest() {Query query = new Query(Criteria.where("age").gte(60));Update update = Update.update("age", -1);mongoTemplate.upsert(query, update, SysUser.class, collectionName);}
}
4.3.2 查找并更新
修改数据时首先对数据进行查询,然后设置需要修改的值,进行数据的更新,如下表所示,可以选择返回更新前或更新后的文档。
方法 | 简要说明 |
---|---|
findAndModify(query, update, entityClass) findAndModify(query, update, collectionName) | 更新相匹配的文档,并返回旧的的文档。 |
findAndModify(query, update, options, entityClass); findAndModify(query, update, options, entityClass, collectionName); | 更新相匹配的文档,并返回旧的或新更新的文档。 |
【注意】没指定集合名称时,会取 @Document注解中的集合名称。
@SpringBootTest
public class UpdateTest {@Resourceprivate MongoTemplate mongoTemplate;private final String collectionName = "UpdateTest";@BeforeEachvoid init() {mongoTemplate.dropCollection(collectionName);List<SysUser> sysUserList = new ArrayList<>();sysUserList.add(SysUser.builder().id("ID10001").name("Tom").age(34).gender("男").build());sysUserList.add(SysUser.builder().id("ID10002").name("Tony").age(23).gender("男").build());sysUserList.add(SysUser.builder().id("ID10003").name("Ross").age(44).gender("女").build());sysUserList.add(SysUser.builder().id("ID10004").name("Gloria").age(14).gender("女").build());sysUserList.add(SysUser.builder().id("ID10005").name("Linda").age(24).gender("女").build());sysUserList.add(SysUser.builder().id("ID10006").name("regina").age(26).gender("女").build());sysUserList.add(SysUser.builder().id("ID10007").name("John").age(22).gender("男").build());sysUserList.add(SysUser.builder().id("ID10008").name("Michael").age(22).gender("男").build());mongoTemplate.save(sysUserList, collectionName);}@Testpublic void findAndModifyTest() {Query query = new Query(Criteria.where("_id").is("ID10001"));Update update = Update.update("name", "张三");mongoTemplate.findAndModify(query, update, SysUser.class, collectionName);}
}
4.4 删除操作
基本删除操作
删除操作同样通过 Query 类构造要删除的条件,然后调用 remove 方法进行删除即可。
方法 | 简要说明 |
---|---|
DeleteResult remove(Object object) DeleteResult remove(Object object, String collectionName) | 用于删除数据,一般都是传递一个主键ID即可。 |
DeleteResult remove(query, entityClass) DeleteResult remove(query, collectionName) DeleteResult remove(query, entityClass, collectionName) | 用于删除符合条件的文档 |
【注意】没指定集合名称时,会取 @Document注解中的集合名称。
@SpringBootTest
public class RemoveTest {@Resourceprivate MongoTemplate mongoTemplate;private final String collectionName = "RemoveTest";@BeforeEachpublic void init() {// 删除集合mongoTemplate.dropCollection(collectionName);List<SysUser> userList = new ArrayList<>();userList.add(new SysUser("1", "白鹿", "女", 31));userList.add(new SysUser("2", "陈都灵", "女", 32));userList.add(new SysUser("3", "高圆圆", "女", 46));userList.add(new SysUser("4", "张含韵", "女", 36));userList.add(new SysUser("5", "李沁", "女", 35));userList.add(new SysUser("6", "胡歌", "男", 43));userList.add(new SysUser("7", "刘亦菲", "女", 38));userList.add(new SysUser("8", "成龙", "男", 71));userList.add(new SysUser("9", "杨幂", "男", 39));userList.add(new SysUser("10", "陈钰琪", "女", 33));mongoTemplate.insert(userList, collectionName);}@Testpublic void removeOne() {Query query = new Query(Criteria.where("id").is("1"));SysUser sysUser = mongoTemplate.findOne(query, SysUser.class, collectionName);if (null != sysUser) {mongoTemplate.remove(sysUser, collectionName);}long count = mongoTemplate.count(query, collectionName);System.out.println("count = " + count);}@Testpublic void removeAll() {Query query = new Query(Criteria.where("age").gte(30));long count = mongoTemplate.count(query, collectionName);System.out.println("删除前,count=" + count);// 删除所有匹配的文档mongoTemplate.remove(query, collectionName);count = mongoTemplate.count(query, collectionName);System.out.println("删除后,count=" + count);}@Testpublic void removeLimit() {Query query = new Query(Criteria.where("age").gte(30));long count = mongoTemplate.count(query, collectionName);System.out.println("删除前,count=" + count);// 删除前两个文档mongoTemplate.remove(query.limit(2), collectionName);count = mongoTemplate.count(query, collectionName);System.out.println("删除后,count=" + count);}
}
查找并删除
方法 | 简要说明 |
---|---|
findAndRemove(query, entityClass) findAndRemove(query, collectionName) | 用于查找并删除单个文档,并可以选择返回删除的文档。如果找不到匹配的文档,则返回 null。 |
findAllAndRemove(query, collectionName) findAllAndRemove(query, entityClass) findAllAndRemove(query, entityClass, collectionName) | 查询出符合条件的所有结果,并将符合条件的所有数据删除。 |
【注意】没指定集合名称时,会取 @Document注解中的集合名称。
@SpringBootTest
public class RemoveTest {@Resourceprivate MongoTemplate mongoTemplate;private final String collectionName = "RemoveTest";@BeforeEachpublic void init() {// 删除集合mongoTemplate.dropCollection(collectionName);List<SysUser> userList = new ArrayList<>();userList.add(new SysUser("1", "白鹿", "女", 31));userList.add(new SysUser("2", "陈都灵", "女", 32));userList.add(new SysUser("3", "高圆圆", "女", 46));userList.add(new SysUser("4", "张含韵", "女", 36));userList.add(new SysUser("5", "李沁", "女", 35));userList.add(new SysUser("6", "胡歌", "男", 43));userList.add(new SysUser("7", "刘亦菲", "女", 38));userList.add(new SysUser("8", "成龙", "男", 71));userList.add(new SysUser("9", "杨幂", "男", 39));userList.add(new SysUser("10", "陈钰琪", "女", 33));mongoTemplate.insert(userList, collectionName);}/*** 删除符合条件的单个文档,并返回删除的文档*/@Testpublic void findAndRemoveTest() {Query query = new Query(Criteria.where("id").is(2));SysUser sysUser = mongoTemplate.findAndRemove(query, SysUser.class);System.out.println("删除的文档数据:" + sysUser.toString());}/*** 删除符合条件的所有文档,并返回删除的文档*/@Testpublic void findAllAndRemoveTest() {Query query = new Query(Criteria.where("age").gte(30));long count = mongoTemplate.count(query, collectionName);System.out.println("删除前,count=" + count);// 删除所有匹配的文档List<SysUser> sysUserList = mongoTemplate.findAllAndRemove(query, collectionName);System.out.println("删除的数据:" + Arrays.toString(sysUserList.toArray()));count = mongoTemplate.count(query, collectionName);System.out.println("删除后,count=" + count);}@Testpublic void findAllAndRemoveLimit() {Query query = new Query(Criteria.where("age").gte(30));long count = mongoTemplate.count(query, collectionName);System.out.println("删除前,count=" + count);// 删除前两个文档List<SysUser> sysUserList = mongoTemplate.findAllAndRemove(query.limit(2), collectionName);System.out.println("删除的数据:" + Arrays.toString(sysUserList.toArray()));count = mongoTemplate.count(query, collectionName);System.out.println("删除后,count=" + count);}
}
五、知识拓展
5.1 查询指定字段的值
在 MongoDB 中,文档是以键值对的形式存储的,每个文档可以包含多个字段,每个字段由一个键和一个值组成。在查询文档时,有时只需要获取文档中的部分字段,而不是全部字段,MongoTemplate 提供了一种简单的方式来查询指定字段的值。
-
查询单个字段的值:要查询单个字段的值,可以使用
findOne
方法,以下是查询单个字段的值的示例代码:Query query = new Query(); query.addCriteria(Criteria.where("name").is("John")); String fieldValue = mongoTemplate.findOne(query, String.class, "users"); System.out.println(fieldValue);
在上面的示例中,创建了一个 Query 对象,并通过 Criteria 来指定查询条件。然后调用 findOne 方法传入查询条件、返回值类型和集合名,它会返回符合条件的第一个文档,并将指定字段的值转换为指定的返回值类型。
-
查询指定字段的值:要查询指定字段的值,可以使用
fields
方法来指定要返回的字段,以下是查询指定字段的值的示例代码:Query query = new Query(); query.addCriteria(Criteria.where("age").gte(18)); query.fields().include("name").exclude("age"); List<User> users = mongoTemplate.find(query, User.class, "users"); for (User user : users) {System.out.println(user.getName()); }
在上面的示例中,使用 fields 方法来指定要返回的字段。在 include 方法中,指定要返回的字段名。在 exclude 方法中,指定要排除的字段名。这样,查询结果中只会包含指定的字段。
5.2 结果类
DeleteResult
此类包含有关已执行删除操作的信息,如下表所示。
方法 | 简要说明 |
---|---|
long getDeletedCount() | 返回已删除的文档数。 |
boolean wasAcknowledged() | 返回写入是否已确认。 |
UpdateResult
此类包含有关已执行更新或替换操作的信息,如下表所示。
方法 | 简要说明 |
---|---|
long getMatchedCount() | 返回匹配的文档数。 |
long getModifiedCount() | 返回已修改文档的数量。 |
BsonValue getUpsertedId() | 如果执行的是一个upsert操作(即先尝试更新,如果没有找到匹配的文档则插入),则返回新插入文档的ID。 如果没有进行upsert操作或者没有插入任何文档,则返回null。 |
boolean isModifiedCountAvailable() |
六、小结
MongoDB 已经被越来越多的使用,它适合于对大量的、无固定数据结构的数据进行存储,本文简单的介绍了通过使用 MongoTemplate 来对 MongoDB 进行 CRUD 的操作。MongoTemplate 提供了一个灵活而强大的方式来操作 MongoDB 数据库,非常适合在 Spring 应用中使用。我们可以根据自己的需求,进一步扩展和优化这些基础操作。
相关文章:
MongoTemplate 基础使用帮助手册
前言 MongoDB 是一种流行的 NoSQL 数据库,适合存储大量的非结构化数据。MongoTemplate 是 Spring Data MongoDB 中的一个核心组件,它提供了一组丰富的 API 来与 MongoDB 进行交互。它封装了许多常见的数据库操作,使开发者能够轻松执行 CRUD 操…...
CCIE与HCIE哪个考试难度更大?
CCIE(思科认证互联网专家)与HCIE(华为认证ICT专家)的考试难度差异体现在技术体系、实验要求及评分标准。2023年全球数据显示,CCIE通过率约25%,HCIE通过率32%,但通过率不能完全反映实际挑战。 C…...
子查询对多层join优化记录
需求背景 查询某个用户是否具有某个角色 表 CREATE TABLE mdm_platform_role_user (ID bigint NOT NULL AUTO_INCREMENT,ROLE_ID varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,USER_ID varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci …...
容器编排利器-k8s入门指南
Kubernetes(K8s)入门指南:容器编排利器 什么是 Kubernetes? Kubernetes(常简称为K8s)是一个开源的容器编排平台,由 Google 开源并交由云原生计算基金会(CNCF)管理。它可以帮助我们自动化部署、扩展和管理容器化应用程序。 为什么需要 Kubernetes? 在微服务架构盛行的今…...
MyBatis—动态 SQL
MyBatis—动态 SQL 一、动态 SQL 的核心作用 动态 SQL 主要解决以下问题: 灵活性:根据不同的输入参数生成不同的 SQL 语句(如条件查询、批量操作)。 可维护性:减少重复代码,通过标签化逻辑提高 SQL 可读…...
解决“VMware另一个程序已锁定文件的一部分,进程无法访问“
问题描述 打开VMware里的虚拟机时,弹出"另一个程序已锁定文件的一部分,进程无法访问"如图所示: 这是VM虚拟机的保护机制。虚拟机运行时,为防止数据被篡改,会将所运行的文件保护起来。当虚拟机崩溃或者强制…...
如何创建一个不可变类
写在前面 如果对象在构造后无法更改,则该对象是不可变的。不可变对象不会以任何方式暴露其他对象来修改其状态; 对象的字段仅在构造函数内初始化一次,并且永远不会再次更改。 1.不可变类的用法 如今,每个软件应用程序的*“必备”规范都是分…...
outbox架构解说
Outbox 模式是一种用于实现数据一致性的架构模式,特别是在微服务架构中。 它确保在处理事务时,数据的原子性和最终一致性。 Outbox 模式的详细解说: 1. 概念与背景 背景:在微服务架构中,一个操作可能涉及多个服务&…...
PT2020 20触控I2C输出IC
1.产品概述 ● PT2020是一款电容式触摸控制ASIC,支持20通道触摸输入,I2C键值输出。可通过I2C调节灵敏度以及功能设置。算法带有走线自补偿功能,具有高抗干扰、宽工作电压范围的突出优势。适用于小家电,智能门锁等消费类…...
【GAN网络入门系列】一,手写字MINST图片生成
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 博主简介:努力学习的22级本科生一枚 🌟;探索AI算法,C,go语言的世界;在迷茫中寻找光芒…...
数据备份与恢复方案
数据备份与恢复方案 一.背景 为确保公司信息安全,防止关键数据丢失,应对突发事件,特制定全面的数据备份与恢复方案。该方案将对公司的各类文件资料进行分级管理,并针对不同级别的数据设定相应的备份策略和恢复流程。 二…...
Go的单测gomock及覆盖率命令
安装gomock: go get github.com/golang/mock/gomockgo get github.com/golang/mock/mockgen 使用 mockgen 生成 mock 代码: 参考 mockgen -sourceservice/user.go -destinationservice/mocks/mock_user_service.go -packagemocks go test -coverprofilecoverage.out…...
淘宝商家层级存在流量上限怎么办,如何突破流量上限?
在淘宝平台运营中,许多商家都会遇到一个共同难题:随着店铺层级的提升,流量增长却逐渐触及天花板。这种现象背后隐藏着平台复杂的流量分配机制,但并非无法破解。 一、流量上限的底层逻辑 淘宝根据商家层级(1-7层&…...
【linux】Web服务—搭建nginx+ssl的加密认证web服务器
准备工作 步骤: 一、 新建存储网站数据文件的目录 二、创建一个该目录下的默认页面,index.html 三、使用算法进行加密 四、制作证书 五、编辑配置文件,可以选择修改主配置文件,但是不建议 原因如下: 自定义一个配置文…...
MySQL MCP 使用案例
## 概述 MySQL MCP(MySQL Multi-Channel Protocol)是MySQL的多通道协议实现,提供了高效的数据库连接池和负载均衡功能。本文档将介绍MySQL MCP的基本使用方法和常见案例。 ## 环境准备 ### 安装MySQL MCP bash pip install mysql-mcp ### 基…...
C#中UI线程的切换与后台线程的使用
文章速览 UI线程切换示例 后台线程使用示例 两者对比适用场景Application.Current.Dispatcher.InvokeTask.Factory.StartNew 执行同步性Application.Current.Dispatcher.InvokeTask.Factory.StartNew 一个赞,专属于你的足迹! UI线程切换 在WPF应用程序…...
实验-实现向量点积-RISC-V(计算机组成原理)
目录 一、实验内容 二、实验步骤 三、源代码 四、实现效果 五、实验环境 六、实验小结与思考 一、实验内容 首先,我们用一个简单的“向量点积”运算作为热身。你将拿到一个不完整的汇编代码“task2-向量点积”,我们的目标是按照C语言描述的功能&a…...
【软考 霍夫曼编码的文档压缩比】
霍夫曼编码的文档压缩比计算基于字符频率的最优编码分配,以下是详细步骤及相关案例: 一、压缩比计算公式 [ \text{压缩比} \frac{\text{压缩前总比特数}}{\text{压缩后总比特数 编码表存储开销}} ] 通常以 比率(如 3:1) 或 百分…...
skywalking使用教程
skywalking使用教程 一、介绍 skywalking 1.1 概念 skywalking是分布式系统的应用程序性能监视工具,专为微服务、云原生架构和基于容器(Docker、K8s、Mesos)架构而设计。SkyWalking 是观察性分析平台和应用性能管理系统,提供分布…...
Tor推出Oniux新工具:为Linux应用提供网络流量匿名化
Tor项目近日发布了名为Oniux的新型命令行工具,该工具可将任何Linux应用程序的网络流量安全地路由至Tor网络,实现匿名化连接。 基于Linux命名空间的隔离技术 与依赖用户空间技巧的torsocks等传统方法不同,Oniux利用Linux命名空间(…...
LLaMA-Factory微调大模型Qwen2.5
1、开始ModelScope社区GPU环境 训练或微调模型都是非常耗费算力的。如果电脑的配置不高,可使用一些云服务器来做这项工作。如ModelScope(魔搭)社区的GPU环境,目前提供36小时免费运算,足够微调一个大模型了。 注册ModelScope(魔搭)社区账号(可能还要注册或认证阿里云账号)…...
docker(四)使用篇二:docker 镜像
在上一章中,我们介绍了 docker 镜像仓库,本文就来介绍 docker 镜像。 一、什么是镜像 docker 镜像本质上是一个 read-only 只读文件, 这个文件包含了文件系统、源码、库文件、依赖、工具等一些运行 application 所必须的文件。 我们可以把…...
算法练习:19.JZ29 顺时针打印矩阵
错误原因 总体思路有,但不够清晰,一直在边调试边完善。这方面就养成更好的构思习惯,以及涨涨经验吧。 分析: 思路:找规律 两个坑: 一次循环的后半段是倒着遍历的是矩阵不是方阵,要考虑行列…...
如何使用 Solana Yellowstone gRPC 重新连接和重放插槽
Yellowstone gRPC 是一个功能强大、可用于生产环境且经过实战检验的工具,用于流式传输实时的 Solana 数据。但在实际条件下,网络中断或服务器重启可能导致连接中断。如果没有适当的重连策略,你的应用程序可能会错过区块链的关键更新。 为了防…...
踩坑:uiautomatorviewer.bat 打不开
错误信息 运行 sdk\tools\bin\uiautomatorviewer.bat 报错 -Djava.ext.dirs..\lib\x86_64;..\lib is not supported. Use -classpath instead. Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit. 原因 java版…...
天能股份SAP系统整合实战:如何用8个月实现零业务中断的集团化管理升级
目录 天能股份SAP系统整合案例:技术驱动集团化管理的破局之路 一、企业背景:新能源巨头的数字化挑战 二、项目难点:制造业的特殊攻坚战 1. 生产连续性刚性需求 2. 数据整合三重障碍 3. 资源限制下的技术突围 三、解决方案:S…...
oracle主备切换参考
主备正常切换操作参考:RAC两节点->单机 (rac和单机的操作区别:就是关闭其它节点,剩一个节点操作即可) 1.主库准备 检查状态 SQL> select inst_id,database_role,OPEN_MODE from gv$database; INST_ID DATA…...
PHP 与 面向对象编程(OOP)
PHP 是一种支持面向对象编程(OOP)的多范式语言,但其面向对象特性是逐步演进而非原生设计。以下是关键分析: 1. PHP 对面向对象编程的支持 核心 OOP 特性: 类和对象: PHP 支持通过 class 关键字定义类&…...
预测模型开发与评估:基于机器学习的数据分析实践
在当今数据驱动的时代,预测模型已成为各行各业决策制定的核心工具。本文将分享我在COMP5310课程项目中开发预测模型的经验,探讨从数据清洗到模型优化的完整过程,并提供详细的技术实现代码。 ## 研究问题与数据集 ### 研究问题 我们的研究聚焦…...
2026《数据结构》考研复习笔记四(绪论)
绪论 前言时间复杂度分析 前言 由于先前笔者花费约一周时间将王道《数据结构》知识点大致过了一遍,圈画下来疑难知识点,有了大致的知识框架,现在的任务就是将知识点逐个理解透彻,并将leetcode刷题与课后刷题相结合。因此此后的过…...
2025-5-16Vue3快速上手
1、reactive创建 对象类型的响应式数据 (1) (2)reactive包裹的对象类型数据是Proxy对象类型 2、ref 创建对象类型的响应式数据 (1)使用js修改ref的数据时依然要加.value (2)ref的底层是用reactive做响应式数据的,因为…...
Lua中使用module时踩过的坑
在lua中设置某个全局对象(假如对象名为LDataUser)为nil时, LDataUser并不会变成nil, 但在有些情况下设置LDataUser nil时却真变成了nil,然后会导致后续再使用LDataUser时会抛nil异常, 后来发现是使用module搞的鬼,下面看看豆包AI给的解释,还…...
WinSCP用户管理FTP详解
1、下载winscp 官方下载地址:https://winscp.net/eng/index.php 2、登录ftp 3、桌面快捷键 4、首页介绍 5、文件搜索 模糊查询,关键字两边必须加’ * ‘号 6、编码报错 报错原因:使用’936(ANS/OEM-简体中尉GBK)’编…...
python基础语法(三-中)
基础语法3: 2.列表与元组: <1>.列表、元组是什么? 都用来存储数据,但是两者有区别,列表可变,元组不可变。 <2>.创建列表: 创建列表有两种方式: [1].a 【】&#x…...
NLP双雄争霸:GPT与BERT的生成-理解博弈——从技术分野到产业融合的深度解码
NLP双雄争霸:GPT与BERT的生成-理解博弈——从技术分野到产业融合的深度解码 前言: 在自然语言处理(NLP)的版图上,GPT与BERT如双子星般照亮了智能时代的语言星空。一个是凭借千亿参数横扫生成任务的“文本造物主”&…...
JS手写代码篇---手写 instanceof 方法
2、手写 instanceof 方法 instancecof用于检测一个对象是否是某个构造函数的实例。它通常用于检查对象的类型,尤其是在处理继承关系时。 eg: const arr [1,2,3,4,5]console.log(arr instanceof Array); // trueconsole.log(arr instanceof Object); // true那这是…...
浮点数截断法:四舍五入的精确模拟
理论解释: 1. 目标 假设 a 3.14159,我们想四舍五入到 小数点后两位(即 3.14 或 3.15)。 2. 步骤拆解 (1) a * 100 把 a 放大 100 倍,让小数点后两位变成整数部分: 3.14159 * 100 314.159 (2) 0.5 关…...
c++ 类的语法3
测试下默认构造函数。demo1: void testClass3() {class Demo { // 没显示提供默认构造函数,会有默认构造函数。public:int x; // 普通成员变量,可默认构造};Demo demo1;//cout << "demo1.x: " << demo1.x << en…...
EasyExcel导出excel再转PDF转图片详解
封装EasyExcel导出工具类 相关的依赖自己网上搜索加上,这里不在阐述 Slf4j Service public class AgentExcelUtils {public String syncDynamicHeadWrite(String fileName,String sheetName,List<List<String>> headList,List<?> data) throws…...
【知识产权出版社-注册安全分析报告-无验证方式导致安全隐患】
前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…...
Oc语言学习 —— 重点内容总结与拓展(上)
隐藏和封装 有四种访问控制符:private(当前类访问权限),package(与映像访问权限相同),protect(子类访问权限),public(公共访问权限)。 访问控制符 1.private(当前类访问权限) 成员变量只能在当前类的内部…...
全面且深度学习c++类和对象(上)
文章目录 过程和对象类的引入,类的定义类的访问限定符及封装类的访问限定符封装 类的实例化类大小内存对齐规则: this指针this特性 过程和对象 C语言面向过程设计,c面向对象设计, 举例:洗衣服 C语言:放衣服…...
QML元素 - RectangularGlow
QML 的 RectangularGlow 是 Qt Quick Effects 模块中专门为矩形元素设计的外发光效果,适用于为卡片、按钮、面板等矩形或圆角矩形添加柔和的边缘光晕,相比通用 Glow 更高效且支持圆角匹配。以下是详细使用技巧和优化指南: 1. 基本用法 impor…...
GraphPad Prism项目的管理
《2025新书现货 GraphPad Prism图表可视化与统计数据分析(视频教学版)雍杨 康巧昆 清华大学出版社教材书籍 9787302686460 GraphPadPrism图表可视化 无规格》【摘要 书评 试读】- 京东图书 GraphPad Prism统计数据分析_夏天又到了的博客-CSDN博客 项目…...
uniapp自定义日历计划写法(vue2)
文章目录 uniapp自定义日历计划写法(vue2)1、效果2、实现源码前言:我们有时候需要实现的日历找不到相应的插件的时候,往往需要手动去写一个日历,以下就是我遇到这样的问题时,手搓出来的一个解决方案,希望可以帮助到更多的人。创作不易,请多多支持uniapp自定义日历计划写…...
差分探头为什么要选择使用屏蔽双绞线
市面上很多各种品牌的差分探头,其使用的线缆都使用了屏蔽双绞线(STP),这主要是因为在测试过程中因高压线路周围强电场或磁场在信号线与地线间感应出共模电压而产生的电磁耦合效应会对测试结果产生干扰,而屏蔽双绞线可以…...
Qt—用SQLite实现简单的注册登录界面
1.实现目标 本次实现通过SQLite制作一个简易的登录窗口,当点击注册按钮时,登录窗口会消失,会出现一个新的注册界面;完成注册或退出注册时,注册窗口会消失,重新出现登录窗口。注册过的用户信息会出现在SQLi…...
Visual Studio旧版直链
[Visual Studio 2019 社区版](https://aka.ms/vs/16/release/vs_community.exe) [Visual Studio 2019 专业版](https://aka.ms/vs/16/release/vs_professional.exe) [Visual Studio 2019 企业版](https://aka.ms/vs/16…...
elementUI源码学习
学习笔记。 最近在看element的table表格优化,又去看了一下element源码框架。element 的架构是很优秀,通过大量的脚本实现工程化,让组件库的开发者专注于事情本身,比如新加组件,一键生成组件所有文件,并完成…...
【LeetCode 热题 100】搜索插入位置 / 搜索旋转排序数组 / 寻找旋转排序数组中的最小值
⭐️个人主页:小羊 ⭐️所属专栏:LeetCode 热题 100 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 搜索插入位置搜索二维矩阵在排序数组中查找元素的第一个和最后一个位置搜索旋转排序数组寻找旋转排序数组中的最小值…...