SpringDataMongoDB-3

自定义Spring Data Repositories的实现

自定义Repositories

SpringData提供了各种各样的方法为了减少代码量,但是如果这些还不能满足我们的要求,可以自己提供repository的实现。两种方式

  1. 独立于SpringData,不适用他提供的一些方法。自己定义接口,自己写实现类。

    这种很简单,不依托SpringData,那它就是一个独立的Bean。按照正常的方式使用就好了

    接口

    public interface CustomerBookRepository extends MongoRepository<Book, String> {// 自己定义的方法,找前10条数据List<Book> findTop10ByName(String name);
    }
    

    实现类

    @Component
    public class CustomerBookRepositoryImpl implements CustomerBookRepository {// 利用它来做查询操作private MongoTemplate mongoTemplate;public CustomerBookRepositoryImpl(MongoTemplate mongoTemplate) {this.mongoTemplate = mongoTemplate;}@Overridepublic List<Book> findTop10ByName(String name) {Criteria condition_1 = Criteria.where("name_1").is(name);Query param = Query.query(condition_1).limit(10);return mongoTemplate.find(param, Book.class);}
    }
  2. 想要用SpringData的一些方法,自己想在这个基础上增加一些自己的方法。

    这种方式比较奇特,按照下面的步骤

    • 定义接口,继承于Repository接口,自定义方法。
    • 写接口实现类,但是这个实现类是不需要继承自定义接口的,方法的签名得一模一样。并且bean的名字为接口名字+Impl(默认是这样,也是可以通过Enable${store}Repositories注解中的repository-impl-postfix来改变,这只是后缀,前缀还是接口名字)。
    • 使用的时候正常注入接口使用。

定义接口

public interface CustomerBookRepository extends MongoRepository<Book, String> {List<Book> findTop10ByName(String name);
}

写接口实现类,但不要继承,方法的签名一样

@Component
public class CustomerBookRepositoryImpl {private MongoTemplate mongoTemplate;public CustomerBookRepositoryImpl(MongoTemplate mongoTemplate) {this.mongoTemplate = mongoTemplate;}public List<Book> findTop10ByName(String name) {Criteria condition_1 = Criteria.where("name_1").is(name);Query param = Query.query(condition_1).limit(10);return mongoTemplate.find(param, Book.class);}
}

测试类


@SpringBootTest(classes = SpringdataMongodbApplication.class)
public class BookQueryMethodRepositoryTest extends BaseApplicationTests {@Autowired //引用接口,private CustomerBookRepository customerBookRepository;@Testpublic void testCustomerFind(){List<Book> go = customerBookRepository.findTop10ByName("go");Assert.isTrue(go.size()<=10);}
}

重写CRUDRepositories

可以重写CRUDRepositories接口的中的方法,在自定义的Repositories里面,只要方法的签名一致就可以。

还是上面例子中的接口,实现类中重写了findAll方法;

@Component
public class CustomerBookRepositoryImpl {private MongoTemplate mongoTemplate;public CustomerBookRepositoryImpl(MongoTemplate mongoTemplate) {this.mongoTemplate = mongoTemplate;}public List<Book> findTop10ByName(String name) {Criteria condition_1 = Criteria.where("name_1").is(name);Query param = Query.query(condition_1).limit(10);return mongoTemplate.find(param, Book.class);}public List<Book> findAll() {System.out.println("CustomerBookRepositoryImpl.findAll");return mongoTemplate.findAll(Book.class);}
}

结果

增加抽象接口

上面的例子还是一个一个的来,要是想提供一个顶级的接口,或者说修改curdrepository 接口中的方法在所有的子类中都有作用。需要按照下面的来

  • 定义顶级接口,继承与curdRepository接口。
  • 增加方法
  • 写实现类,实现自定义接口,并且继承于SimpleMongoRepository(取决于具体的模块,比如Jpa就是SimpleJpaRepository)。
  • 在@Enable{store}Repositories(@EnableMongoRepositories)将实现类配置给repositoryBaseClass属性
  • 像前面的一样,自己写接口,继承于顶级接口,做操作。

定义接口,定义方法

@NoRepositoryBean
public interface BaseRepository<T, ID> extends CrudRepository<T, ID> {// 自定义方法List<T> baseCustomerQuery();
}

写实现类

​ 实现接口,继承SimpleMongoRepository,注意,这里的类名,和上一章节的没有关系,随便写。

public class BaseRepositoryImplfdfdfd<T, ID> extends SimpleMongoRepository<T, ID> implements BaseRepository<T,ID>{public BaseRepositoryImplfdfdfd(MongoEntityInformation<T, ID> metadata, MongoOperations mongoOperations) {super(metadata, mongoOperations);}public List<T> baseCustomerQuery() {System.out.println("BaseRepositoryImpl.baseCustomerQuery");return super.findAll();}
}

在@EnableMongoRepositories中配置

@SpringBootApplication
@EnableMongoRepositories(repositoryBaseClass = BaseRepositoryImplfdfdfd.class) // 配置
public class SpringdataMongodbApplication {public static void main(String[] args) {SpringApplication.run(SpringdataMongodbApplication.class, args);}
}

测试类

在测试类中正常使用

先定义接口

public interface BaseBookRepository extends BaseRepository<Book,String> {}

在写测试类

public class BaseTest extends BaseApplicationTests {@Autowiredprivate BaseBookRepository baseBookRepository;@Testpublic void testBaseFind0(){System.out.println(baseBookRepository.baseCustomerQuery().size());}
}

结果

还可以通过这种方式重写 CrudRepository中的方法,比如findAll方法。比如现在要重写,如果不打算提供抽象接口的话,直接继承于SimpleMongoRepository,重写他的findAll方法就好了

Spring Data MongoDB中还有一个很方便的工具类,MongoTemplate,上面说的这些Repository底层都是通过它来实现的,下面的章节来介绍一下它的一些使用方式

MongoTemplate使用

大多数的情况下,它都是在Spring的环境下使用的,它也支持单独使用,按照下面的方式

public class MongoApp {private static final Log log = LogFactory.getLog(MongoApp.class);public static void main(String[] args) throws Exception {// 需要通过MongoClients.来创建client,并且指定操作的数据库MongoOperations mongoOps = new MongoTemplate(MongoClients.create(), "database");mongoOps.insert(new Person("Joe", 34));log.info(mongoOps.findOne(new Query(where("name").is("Joe")), Person.class));mongoOps.dropCollection("person");}
}

需要通过MongoClients来创建MongoClient,指定数据库就可以使用了。这不是我们的重点,重点是介绍它的使用

是什么

  1. MongoTemplate是SpringData MongoDB中的核心类,提供CRUD和贴合MongoDB的操作(聚合,索引),并且提供了Document(MongoDB中的概念)和实体对象之间的映射操作。

  2. 它配置好了之后,就是线程安全的。

  3. Document和实体对象之间的转换是通过MongoConverter 接口来实现的,Spring默认提供的是MappingMongoConverter,当然,我们也可以自定义。

  4. 将MongoDB的错误转换成更加切合Spring的错误。

  5. 保留了原始的通过MongoClient来访问的操作。

保存,更新,删除操作

保存

有下面的几个保存的方法

save方法等于MongoDB语句中的save操作,遇到_id一样的会替换掉(但是不推荐使用,多数情况下还是使用insert开头的),在保存的时候如果主键字段没有值(_id字段对应的属性),会自动生成,但是这个字段的类型只能为String,ObjectId,BigInteger,在CRUD的时候,SpringData MongoDB会自动的转换(转换为ObjectId),如果转换不了,就不会转换。只用原始的值,如果不想要它的这种转化,在_id字段上用@MongoId注解来标注,表示不需要转换。比如:

需要转换

public class Student {private String id;private String name;private Integer age;private Double score;
}

不需要转换

public class Student {@MongoIdprivate String id;private String name;private Integer age;private Double score;
}

insert开头的方法对应的是MongoDB中的insert,支持集合,单个对象的插入,后面的String参数或者Class<?>参数可以直接传递集合的名字,也可以和这个集合对应的实体对象.

测试实体类

@Data
@Accessors(chain = true)
@Document
@ToString
public class Student {private String id;private String name;private Integer age;private Double score;private Book book;
}

构建测试数据

    static List<Book> buildBooks(int count) {ArrayList<Book> param = new ArrayList<>();List<String> bookName = Arrays.asList("java", "go", "php", "c", "c++", "Mysql");ThreadLocalRandom current = ThreadLocalRandom.current();LocalDate today = LocalDate.now();for (int i = 0; i < 1000; i++) {String name = bookName.get(current.nextInt(bookName.size()));Book book = new Book().setCount(current.nextInt(1000)).setName(name).setPrice(current.nextDouble(100)).setPublishTime(today.minusDays(current.nextInt(30))).setCount(current.nextInt(1000)).setShortName(name + ":" + name);param.add(book);}return param;}static List<Student> buildStudents(int count) {List<Book> books = buildBooks(count);ArrayList<Student> res = new ArrayList<>();List<String> names = Arrays.asList("小红", "小黄", "小蓝", "小绿", "小青", "小粉");ThreadLocalRandom current = ThreadLocalRandom.current();for (int i = 0; i < count; i++) {Student student = new Student().setId(String.valueOf(UUID.randomUUID())).setName(names.get(current.nextInt(names.size()))).setAge(current.nextInt(100)).setScore(current.nextDouble(100)).setBook(books.get(current.nextInt(books.size())));res.add(student);}return res;}

例子:

@Testpublic void testSave() {List<Student> students = buildStudents(100);// 插入多条数据,传递的是实体对象Collection<Student> students1 = mongoTemplate.insert(students, Student.class);Assert.isTrue(students1.size() == 100);//插入多条数据,指定集合名称Collection<Student> t_student = mongoTemplate.insert(students, "t_student");Assert.isTrue(t_student.size() == 100);//插入单个数据Student student = mongoTemplate.insert(students.get(0));Assert.notNull(student);//插入单个数据,指定集合的名称Student student_1 = mongoTemplate.insert(students.get(0),"t_student");Assert.notNull(student_1);// 分段式操作,可以选择Collection,还是用bulk来选择ExecutableInsertOperation.ExecutableInsert<Student> bookExecutableInsert = mongoTemplate.insert(Student.class);Collection<? extends Student> t_student1 = bookExecutableInsert.inCollection("t_student").all(students);Assert.isTrue(t_student1.size() == 100);}

更新

这些都是和MongoDB的语法对应上的,也就是换了一种写法。命令的参数分为三个部分

  • 查询操作,(查询操作在后面会详细的说)
  • 更新操作
  • 实体对象。或者集合名称。
   @Testpublic void testUpdate() {Criteria criteria = Criteria.where("_id").is(new ObjectId("626bcdd98646873e6f83e94f"));Update update = Update.update("name", "name-test");UpdateResult updateResult = mongoTemplate.updateFirst(Query.query(criteria), update, Student.class);System.out.println(updateResult);}

主要说说Update对象

Update对象对应的是MongoDB 更新语句中的update块。MongoDB语法里面有的,Update对象里面也有。比如 s e t , set, set,rename等,可以看Methods in the Update Class

在使用的时候可以直接创建Update对象,或者通过它的静态方法来创建Update.update(String key, @Nullable Object value)。比如下面的例子

  @Testpublic void testUpdate1() {Criteria criteria = Criteria.where("_id").is(new ObjectId("626bcdd98646873e6f83e94f"));Update update = new Update().rename("name", "name_1").currentDate("data_time");UpdateResult updateResult = mongoTemplate.updateFirst(Query.query(criteria), update, Student.class);Assert.isTrue(updateResult.getModifiedCount() > 0);}

对应的MongoDB的语句为

db.student.updateOne(
{_id:ObjectId("626bcdd98646873e6f83e94f")
},
{$currentDate:{data_time:true},$rename:{"name":"name_1"}
}
);

此还,还有findAndModify类似的方法,也都是和MongoDB一一对应。它还支持FindAndModifyOptions来设置属性,比如upsert,new等。

  @Testpublic void testUpdate2(){Criteria criteria = Criteria.where("_id").is(new ObjectId("626bcdd98646873e6f83e94f"));Update update = new Update().currentDate("data_time");//设置newFindAndModifyOptions findAndModifyOptions = FindAndModifyOptions.options().returnNew(true);Student andModify = mongoTemplate.findAndModify(Query.query(criteria), update, findAndModifyOptions, Student.class);System.out.println(andModify);}

删除

以remove开头

同样的,也是和mongoDB的语法是对应的

@Testpublic void testDelete0(){Criteria criteria = Criteria.where("name").is("小粉");DeleteResult remove = mongoTemplate.remove(Query.query(criteria), Student.class);System.out.println(remove);}

还可以使用update方法中的聚合操作 Aggregation Pipeline Updates

还可以使用更加精细的控制方式来更新 Finding and Replacing Documents

乐观锁

SpringData MongoDB也提供了JPA那样的乐观锁机制。使用@Version注解,每次数据更新版本号就会加1,当然版本号也是保存在数据库中的。如果当前更新的版本落后于数据库的版本就会报错(OptimisticLockingFailureException )。

@Data
@Accessors(chain = true)
@Document
@ToString
public class Student {@MongoIdprivate String id;private String name;private Integer age;private Double score;private Book book;@Versionprivate Long v;
}
    @Testpublic void testLock() {Student student = buildStudents(1).get(0); // 构建一条数据Student c = mongoTemplate.insert(student);   // 插入数据,version 还是0Student byId = mongoTemplate.findById(c.getId(), Student.class); // 查找刚刚加载的数据,版本还是0,c.setName("name111"); // 修改mongoTemplate.save(c);  // 保存,修改,这个时候version变为1了,save方法在id相等的时候会替换mongoTemplate.save(byId); //保存,但是这个版本是0,就会报错 OptimisticLockingFailureException}

查询

有两种方式

  1. 使用他们提供的流式的API
  2. 自己写json。

自己写json

构建BasicQuery对象,传递给mongoTemplate来查询

 @Testpublic void testFind1(){BasicQuery basicQuery = new BasicQuery("{\n" +"    name:\"小红\",\n" +"    \"book.count\":{$gt:50}\n" +"}");List<Student> students = mongoTemplate.find(basicQuery, Student.class);Criteria criteria = Criteria.where("name").is("小红").andOperator(Criteria.where("book.count").gt(50));List<Student> students1 = mongoTemplate.find(Query.query(criteria), Student.class);// 两种方式 比对一下,看是否正确,,这里得重写equals和hashcode方法Assertions.assertEquals(students,students1);}

原始的mongoDB的查询语句

db.student.find(
{name:"小红","book.count":{$gt:50}
}
)

使用他们提供的流式的API

查询分为两个部分,Query对象和Criteria。他们的方法名和MongoDB中的运算符的名字一样的。

Criteria中的方法如下:

Methods for the Criteria Class

Query中的方法如下:

Methods for the Query class

选择字段展示(Select)

操作Query对象中的Field的include()exclude()来选择字段

可以使用投影操作

query.fields().project(MongoExpression.create("'$toUpper' : '$last_name'"))         .as("last_name");

Distinct 操作

 @Testpublic void testFind2(){// 两种方式Criteria age = Criteria.where("age").gt(40);List<String> students = mongoTemplate.findDistinct(Query.query(age), "name", Student.class,String.class);//List<String> name = mongoTemplate.query(Student.class).distinct("name").matching(age).as(String.class).all();Assertions.assertArrayEquals(students.toArray(new String[]{}),name.toArray(new String[]{}));}

对应的MongoDB的语句

db.student.distinct(
"name",{age:{$gt:40}}
)

全文查询

具体的可以看 Full-text Queries

前提是得先创建好全文索引

Query query = TextQuery.queryText(new TextCriteria().matchingAny("coffee", "cake")).sortByScore() .includeScore(); List<Document> page = template.find(query, Document.class);

流式API

通过它可以更加灵活的做操作,在和更加的底层的交互的时候,可以通过它来做,在query,update,insert返回类里有不同的操作。

 @Testpublic void testFind4(){//查询long ageCount = mongoTemplate.query(Student.class).matching(Query.query(Criteria.where("age").gt(10))).count();System.out.println(ageCount);//跟新UpdateResult first = mongoTemplate.update(Student.class).matching(Query.query(Criteria.where("age").gt(10))).apply(new Update().inc("age", 1)).first();// 添加mongoTemplate.insert(Student.class).one(buildStudents(1).get(0));}

通过Example查询(QBE)

Example由三个部分组成

  • Probe:Example关联的实体对象,实体对象里面有多个字段。
  • ExampleMatcher:用来做匹配的,包含如何匹配特定字段的详细信息。
  • Example:用来创建查询的,Example是由probe和ExampleMatcher组成的。

Example限制

  • 不支持嵌套查询或者分组的查询,比如firstname = ?0 or (firstname = ?1 and lastname = ?2)
  • 只支持start/contains/ends/regex 匹配和其他类型的精确匹配。

最后还是通过Example对象来构建Criteria对象,封装为Query对象来查询

包装类型如果没有值在查询的时候会忽略,基本类型会按照默认值来处理<

例子

通过mongoTemplate来使用

  @Testpublic void testFind5(){Student student = new Student().setName("小红");Example<Student> of = Example.of(student);Student one = mongoTemplate.findOne(Query.query(Criteria.byExample(of)), of.getProbeType());System.out.println(one);}

通过QueryByExampleExecutor来使用

QueryByExampleExecutor是一个接口,自定义的接口需要实现这个接口,可以直接使用它提供的一些方便的方法。CrudRepository没有实现,但是MongoRepository实现了,主要我们的接口继承它,就可以直接用。

简单

  @Testpublic void testFind(){Student student = new Student().setName("小红");Example<Student> of = Example.of(student);List<Student> all = studentCrudRepository.findAll(of);all.forEach(System.out::println);}

复杂

  @Testpublic void testFind(){Student student = new Student().setName("小红");Example<Student> of = Example.of(student);// 通过Function做转换List<Student> all = studentCrudRepository.findBy(of, new Function<FluentQuery.FetchableFluentQuery<Student>, List<Student>>() {@Overridepublic List<Student> apply(FluentQuery.FetchableFluentQuery<Student> studentFetchableFluentQuery) {Sort ascending = Sort.sort(Student.class).by(Student::getAge).ascending();return studentFetchableFluentQuery.sortBy(ascending).all();}});all.forEach(System.out::println);}

可以通过ExampleMatcher来做更加精细的控制,详细的看Example Matchers

  @Testpublic void testFind7(){Student student = new Student().setName("小");ExampleMatcher matcher = ExampleMatcher.matching()// 给name字段,调整匹配,.withMatcher("name",matcher1 -> {// name字段前缀开头。 这里能查到所有以小开头的name值matcher1.startsWith();});Example<Student> of = Example.of(student,matcher);studentCrudRepository.findAll(of).forEach(System.out::println);}

聚合操作

聚合操作文档-MongoDB

聚合操作文档-SpringData MongoDB

三个核心概念

  • Aggregation

    代表的是MongoDB中的aggregate操作,通过它来表示聚合操作,它是由Aggregation的newAggregation(…)的静态方法来创建,可以将多个pipeline聚合在一块。

  • AggregationDefinition

    代表MongoDB pipeline 的操作。通过Aggregate来创建AggregateOperation。

  • AggregationResults

    聚合结果的返回值,它持有原始的返回值。

使用方式如下:

import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;Aggregation agg = newAggregation(pipelineOP1(),pipelineOP2(),pipelineOPn()
);AggregationResults<OutputType> results = mongoTemplate.aggregate(agg, "INPUT_COLLECTION_NAME", OutputType.class);
List<OutputType> mappedResult = results.getMappedResults();

SpringData MongoDB支持的聚合操作

Supported Aggregation Operations

例子:

mongoDB语法:

还是上面说的student的例子,先做投影,在做分组,分组是按照name和book.name分组,在由一些的函数操作。强烈推荐使用 Aggregation来创建pipline,聚合pipline

db.student.aggregate({$project:{name_1:"$name",age:1,score:1,book:1}},{$group:{_id:{name:"$name_1",bookName:"$book.name"},count:{$sum:1},bookCount:{$sum:"$book.count"},priceArray:{$push:"$book.price"}}},{$sort:{bookCount:1}}
)

java代码

 @Testpublic void testFind8(){ProjectionOperation projectionOperation = Aggregation.project("age", "score", "book").and("name").as("name_1");GroupOperation groupOperation = Aggregation.group("name_1", "book.name").sum("book.count").as("bookCount").count().as("count").push("book.price").as("priceArray");SortOperation sortOperation = Aggregation.sort(Sort.by("bookCount").ascending());Aggregation aggregation = Aggregation.Aggregation(projectionOperation, groupOperation,sortOperation);AggregationResults<Map> student = mongoTemplate.aggregate(aggregation, "student", Map.class);List<Map> mappedResults = student.getMappedResults();mappedResults.forEach(System.out::println);}

写好每个阶段,通过Aggregation.Aggregation聚合将多个聚合在一块。Aggregation中聚合操作中的支持的每个阶段。很方便。

更多的例子看官网的样子,还得自己多来

Aggregation Framework Examples

索引操作

相关的操作被封装为IndexOperations,可以通过mongoTemplate来操作

创建索引

 @Testpublic void testFind9(){//创建mongoTemplate.indexOps(Student.class).ensureIndex(new Index("age", Sort.Direction.ASC).named("idx_age"));// 查找ArrayList<Object> collect = mongoTemplate.indexOps(Student.class).getIndexInfo().stream().collect(ArrayList::new, (t, t1) -> {t.add(t1.getName());}, ArrayList::addAll);Assertions.assertTrue(collect.contains("idx_age"));}

指定Callbacks

可以通过execute 方法来直接对原生的api来操作,在Spring template 的这些类里面,基本的思想是,将所有的操作都通过execute的回调方法来执行,比如JdbcTemplate,这样做是为了确保异常和任何的资源可以在一个地方统一的管理和处理。

操作原生的API来获取索引的名字。

 @Testpublic void testFind10(){List<String> name = mongoTemplate.execute(Student.class, new CollectionCallback<List<String>>() {@Overridepublic List<String> doInCollection(MongoCollection<Document> collection) throws MongoException, DataAccessException {return Streamable.of(collection.listIndexes()).stream().map(t -> t.getString("name")).collect(Collectors.toList());}});System.out.println(name);}

有关SpringDataMongoDB和MongoTemplate相关的操作就介绍到这里了,这些常用的API都是和MongoDB的命令对应的,这里列举的不全,这也不难,多写写就熟悉了。还有一些SpringData MongoDB的内容没有说,后面再说。


关于博客这件事,我是把它当做我的笔记,里面有很多的内容反映了我思考的过程,因为思维有限,不免有些内容有出入,如果有问题,欢迎指出。一同探讨。谢谢。

SpringDataMongoDB-3相关推荐

  1. dubbo服务使用spring-data-mongodb进行时间查询的bug记录

    一.项目情况:spring-boot+mongodb+dubbo. 二.问题:调用dubbo服务并使用spring-data-mongodb的gte,lte时间段比较查询, @Reference(re ...

  2. Spring-Data-MongoDB的Index注解的expireAfterSeconds参数不起作用?解决方案居然是这样的!...

    2019独角兽企业重金招聘Python工程师标准>>> Spring-Data-MongoDB是一个很好用的MongoDB操作组件,但最近在使用时有一个集合需要给数据指定过期时间,因 ...

  3. spring-data-mongodb与mongo shell的对应关系

    除了特殊注释外,本文的测试结果均基于 spring-data-mongodb:1.10.6.RELEASE(spring-boot-starter:1.5.6.RELEASE),MongoDB 3.0 ...

  4. 大数据之mongodb -- (2)java集成 MongoDB 3.2,使用Spring-data-mongodb进行集成

    Java集成MongoDB有很多方式,可以直接用mongodb的java驱动程序来发送语句到mongodb服务器,也可以用第三方的工具包来做. (1) 选择版本 选择的就是springdata集成的m ...

  5. MongoDB✧SpringDataMongoDB

    SpringDataMongoDB 使用Spring Data 框架都是按照面向对象思想操作用于的工具.使用Spring Data Mongodb 也是使用面向对象的方式进行操作MongoDB,省略了 ...

  6. MongoDB与Spring整合(支持事务)——SpringDataMongoDB

    1.将MongoDB设置为复制集模式 a.修改 mongod.cfg 文件,添加replSetName复制集名称 #replication: replication:replSetName: &quo ...

  7. 关于Spring-Data-Mongodb中的project()的用法,和previousOperation()的用法

    最近使用Spring-Data-Mongodb的API来改写原来的代码,遇到了一些问题,先把自己学到的一些东西总结下来. 参考: http://www.cnblogs.com/ontheroad_le ...

  8. spring-data-mongodb必须了解的操作

    http://docs.spring.io/spring-data/data-mongo/docs/1.0.0.M5/api/org/springframework/data/mongodb/core ...

  9. spring-data-mongodb查询结果返回指定字段

    方法1 DBObject dbObject = new BasicDBObject(); dbObject.put("status", 1); DBObject fieldObje ...

  10. 使用spring-data-mongodb操作mongodb

    mongodb.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="h ...

最新文章

  1. python单例模式基于__new__方法实现的单例模式(推荐使用,方便)
  2. 【洛谷搜索专题Python和C++解】DFS和BFS经典题目(陆续补充)
  3. linux内核网络协议栈--数据包的网卡驱动收发包过程(二十五)
  4. Linux xsync分发脚本完整内容
  5. Linux学习之ARM开发板连接ubuntu18.04LTS及NFS相关配置
  6. hadoop项目实战--ETL--(三)实现mysql表到HIVE表的全量导入与增量导入
  7. 【Elasticsearch】7.9 单字段支持的最大字符数
  8. css关键字unset
  9. ASP.NET ZERO 学习 JTable的使用
  10. c++ 指针与引用区别
  11. ajax实现文件上传6,实现Ajax文件上传功能
  12. SVN可视化管理工具
  13. android绘制半圆弧线_半圆形进度条Android - 绘制半圆
  14. HBuilder使用夜神模拟器
  15. shiro.crypto.CryptoException: Unable to correctly extract the Initialization Vector or ciphertext
  16. Flutter 布局报错The following assertion was thrown during performLayout():
  17. magisk卸载内置软件_Win10自带软件怎么卸载 Win10自带软件卸载方法【详细教程】...
  18. LinuxC编程中常见的段错误(非法操作内存)情形
  19. html中图片自动循环滚动代码,实现长图片自动循环滚动效果
  20. Unity 图形 - 摄像机

热门文章

  1. 线上投票表决软件哪个好用些?
  2. 服务器cmos放电后桌面无内容,cmos中放电后,怎么设置?
  3. 闪存备份,记录平时一些小随笔
  4. 保险行业“数字化赋能企业运营管理”
  5. UML时序图和流程图介绍
  6. HTML页面herf点击不跳转
  7. c语言读txt文件的数据与写数据到txt文件
  8. 用物理学和域知识训练“无标注样本的”神经网络( Outstanding Paper Award 优秀论文奖)
  9. idea导出jar包无法运行
  10. 写给未来自己的信(2011,2019,2029,2039)