Spring-data-mongodb使用手册
- 格式:doc
- 大小:538.50 KB
- 文档页数:14
Springdatamongodb聚合,投射,内嵌数组⽂档分页.尽量别直接⽤ DBObject ,Spring data mongodb 的api 本来就没什么多⼤⽤处,如果还直接⽤ DBObject 那么还需要⾃⼰去解析结果,说动做个对象映射,累不累Spring data mongodb 唯⼀好处就是,不需要⾃⼰decode encode,其他别的⼏乎也没了DBObject project = new BasicDBObject("$project", new BasicDBObject("_id", 1).append("..", "$..").append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1));query.add(project);query.add(new BasicDBObject("$unwind", "$..."));query.add(new BasicDBObject("$skip",...));query.add(new BasicDBObject("$limit",...));AggregationOutput aggregationOutput = mongoTemplate.getCollection("...").aggregate(query);以下使⽤Spring data mongodb 做聚合,内嵌⽂档分页,订单 - 明细⼀对多的例⼦package com.example.mongo.entity;import lombok.Data;import lombok.experimental.Accessors;import org.bson.types.ObjectId;import org.springframework.data.annotation.Id;import java.io.Serializable;import java.util.List;/*** Created by laizhenwei on 2017/11/9*/@Data@Accessors(chain = true)public class Order implements Serializable {private static final long serialVersionUID = 4738576111790390042L;@Idprivate ObjectId objectId;private List<Detail> details;/*** 企业编号*/private String compyCode;/*** 订单号*/private String orderNo;/*** ⽤户名*/private String userName;}明细实体package com.example.mongo.entity;import lombok.Data;import lombok.experimental.Accessors;import org.bson.types.ObjectId;import java.io.Serializable;import java.math.BigDecimal;/*** Created by laizhenwei on 2017/11/9*/@Data@Accessors(chain = true)public class Detail implements Serializable {private static final long serialVersionUID = 942116549431791887L;private ObjectId id;/*** 商品名称*/private String productName;/*** 商品数量*/private Long itemQty;/*** 单价*/private BigDecimal price;}Junitpackage com.example.mongo.Repository;import com.example.mongo.entity.Detail;import com.example.mongo.entity.Order;import com.mongodb.BasicDBList;import com.mongodb.DBObject;import lombok.Data;import org.bson.types.ObjectId;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.data.annotation.Id;import org.springframework.data.mongodb.core.MongoTemplate;import org.springframework.data.mongodb.core.aggregation.Aggregation;import org.springframework.data.mongodb.core.aggregation.AggregationOperation;import org.springframework.test.context.junit4.SpringRunner;import java.math.BigDecimal;import java.util.ArrayList;import java.util.List;import java.util.Optional;import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;import static org.springframework.data.mongodb.core.aggregation.Aggregation.limit;import static org.springframework.data.mongodb.core.query.Criteria.where;/*** Created by laizhenwei on 2017/11/9*/@RunWith(SpringRunner.class)@SpringBootTestpublic class OrderTests {@Autowiredprivate OrderRepository orderRepository;@Autowiredprivate MongoTemplate mongoTemplate;private String[] compyCode = {"123123", "456456", "789789"};private String[] userNames = {"Athos", "Peter", "Nero", "Gavin", "Carter"};/*** 造⼀点数据*/@Testpublic void save() {List<Order> orders = new ArrayList<>(200);for (int i = 0; i < 200; i++) {List<Detail> details = new ArrayList<>(3);for (int j = 0; j < 3; j++) {Detail detail = new Detail();detail.setId(new ObjectId());detail.setItemQty((long) (i + 1));detail.setProductName("产品" + i + "_" + j);detail.setPrice(new BigDecimal(10 + i));details.add(detail);}Order order = new Order();order.setCompyCode(compyCode[i % 3]);order.setUserName(userNames[i % 5]);order.setOrderNo(String.valueOf(i));order.setDetails(details);orders.add(order);}orderRepository.insert(orders);}/*** 内嵌⽂档分页查询*/@Testpublic void pageQuery() {Detail detailDto = new Detail();detailDto.setProductName("产品19_0");List<AggregationOperation> commonOperations = new ArrayList<>(9);commonOperations.add(project("objectId", "details", "compyCode", "orderNo", "userName").and("details").as("detail"));Optional.ofNullable(detailDto.getProductName()).ifPresent(s -> commonOperations.add(match(where("details.productName").is(detailDto.getProductName()))));commonOperations.add(unwind("detail"));List<AggregationOperation> pageOperations = new ArrayList<>(commonOperations);pageOperations.add(skip(1l));pageOperations.add(limit(10));List<AggregationOperation> totalAggOperation = new ArrayList<>(commonOperations);totalAggOperation.add(group().count().as("total"));List<DetailVo> results = mongoTemplate.aggregate(Aggregation.newAggregation(Order.class,pageOperations), Order.class, DetailVo.class).getMappedResults();System.out.println(results.size());DBObject rawResults = mongoTemplate.aggregate(Aggregation.newAggregation(Order.class,totalAggOperation), String.class).getRawResults();BasicDBList result = (BasicDBList)rawResults.get("result");long total = result.isEmpty() ? 0 : Long.parseLong(((DBObject)result.get(0)).get("total").toString());System.out.println("total:" + total);}/*** 结果实体*/@Dataprivate static class DetailVo{@Idprivate ObjectId orderId;private Detail detail;private String compyCode;private String orderNo;private String userName;}}logback 打开⽅便观察<Logger name="org.mongodb.driver" level="debug" /><logger name="org.springframework.data.mongodb.core.MongoTemplate" level="debug" />控制台输出,只取重点,因为skip 了⼀个,所以结果只有2个,总数量是3个13:45:31.740 logback [main] DEBUG o.s.data.mongodb.core.MongoTemplate - Executing aggregation: { "aggregate" : "order" , "pipeline" : [ { "$project" : { "objectId" : "$_id" , "details" : 1 , "compyCode" : 1 , "orderNo" : 1 , "userName" : 1 , "detai 13:45:31.743 logback [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[e9]13:45:31.752 logback [main] INFO org.mongodb.driver.connection - Opened connection [connectionId{localValue:2}] to 192.168.1.9:2702313:45:31.756 logback [main] DEBUG mand - Sending command {aggregate : BsonString{value='order'}} to database e9 on connection [connectionId{localValue:2}] to server 192.168.1.9:2702313:45:31.759 logback [main] DEBUG mand - Command execution completed13:45:31.765 logback [main] DEBUG o.s.d.m.c.i.MongoPersistentEntityIndexCreator - Analyzing class class com.example.mongo.Repository.OrderTests$DetailVo for index information.213:45:31.780 logback [main] DEBUG o.s.data.mongodb.core.MongoTemplate - Executing aggregation: { "aggregate" : "order" , "pipeline" : [ { "$project" : { "objectId" : "$_id" , "details" : 1 , "compyCode" : 1 , "orderNo" : 1 , "userName" : 1 , "detai 13:45:31.780 logback [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[e9]13:45:31.780 logback [main] DEBUG mand - Sending command {aggregate : BsonString{value='order'}} to database e9 on connection [connectionId{localValue:2}] to server 192.168.1.9:2702313:45:31.782 logback [main] DEBUG mand - Command execution completedtotal:3。
SpringBoot中MongoDB注解概念及使⽤spring-data-mongodb主要有以下注解@Id主键,不可重复,⾃带索引,可以在定义的列名上标注,需要⾃⼰⽣成并维护不重复的约束。
如果⾃⼰不设置@Id主键,mongo会⾃动⽣成⼀个唯⼀主键,并且插⼊时效率远⾼于⾃⼰设置主键。
原因可参考上⼀篇mongo和mysql的性能对⽐。
在实际业务中不建议⾃⼰设置主键,应交给mongo⾃⼰⽣成,⾃⼰可以设置⼀个业务id,如int型字段,⽤⾃⼰设置的业务id来维护相关联的表。
@Document标注在实体类上,类似于hibernate的entity注解,标明由mongo来维护该表。
@Indexed声明该字段需要加索引,加索引后以该字段为条件检索将⼤⼤提⾼速度。
唯⼀索引的话是@Indexed(unique = true)。
也可以对数组进⾏索引,如果被索引的列是数组时,MongoDB会索引这个数组中的每⼀个元素。
也可以对整个Document进⾏索引,排序是预定义的按插⼊BSON数据的先后升序排列。
也可以对关联的对象的字段进⾏索引,譬如User对关联的address.city进⾏索引。
@CompoundIndex复合索引,加复合索引后通过复合索引字段查询将⼤⼤提⾼速度。
写法如上,lastName和age将作为复合索引,数字参数指定索引的⽅向,1为正序,-1为倒序。
⽅向对单键索引和随机存不要紧,但如果你要执⾏分组和排序操作的时候,它就⾮常重要了。
@Field代表⼀个字段,可以不加,不加的话默认以参数名为列名。
@Transient被该注解标注的,将不会被录⼊到数据库中。
只作为普通的javaBean属性。
@DBRef关联另⼀个document对象。
类似于mysql的表关联,但并不⼀样,mongo不会做级联的操作。
先来看⼀下不加DBRef时,mongo保存数据的情况:Article类有String title,List pictureList,两个属性,Picture有⼀个url,⼀个desc属性。
[SpringDataMongoDB]学习笔记--MongoTemplate插⼊修改操作插⼊操作:直接给个例⼦import static org.springframework.data.mongodb.core.query.Criteria.where;import static org.springframework.data.mongodb.core.query.Criteria.query;…Person p = new Person("Bob", 33);mongoTemplate.insert(p);//还可以多加⼀个参数,来提供collectionname。
⽐如insert(p,"person").Person qp = mongoTemplate.findOne(query(where("age").is(33)), Person.class);collection document的名字有下⾯⼏种⽅式:1. 默认为类名,并且⾸字母⼩写。
⽐如com.test.Person -> person2. 通过在类名上增加标记@Document 来指定。
3. 在执⾏操作时,把collectionname作为参数传递进去。
主要操作: insert,insertAll, save(当object不存在时,执⾏insert)。
更新操作:import static org.springframework.data.mongodb.core.query.Criteria.where;import static org.springframework.data.mongodb.core.query.Query;import static org.springframework.data.mongodb.core.query.Update;...WriteResult wr = mongoTemplate.updateMulti(new Query(where("accounts.accountType").is(Account.Type.SAVINGS)),new Update().inc("accounts.$.balance", 50.00),Account.class);主要操作: updateFirst(更新第⼀个匹配的), updateMulti(更新所有匹配的)upsert操作:template.upsert(query(where("ssn").is(1111).and("firstName").is("Joe").and("Fraizer").is("Update")), update("address", addr), Person.class);先查询,如果没有符合条件的,会执⾏插⼊,插⼊的值是查询值+更新值。
Spring Data MongoDB 查询指南Spring Data MongoDB 中的查询指南1. 概述本文将关注在Spring Data MongoDB 中构建不同类型的查询。
我们将查看使用Query 和Criteria 类查询ducument、自动生成的查询方法、JSON 查询和QueryDSL。
1.1. Maven 依赖如果你希望使用Spring Data MongoDB,你需要加入以下条目到你的pom.xml 文件:<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-mongodb</artifactId><version>1.9.6.RELEASE</version></dependency>最新版本可以在这里找到。
2. Document 查询使用Spring Data 查询MongoDB的一种常见方法是使用Query 和Criteria 类,它们非常接近原生操作。
2.1. is这只是一个使用相等的criterion,让我们看看它是如何工作的。
在以下示例中,我们查找名为Eric 的用户。
让我来看看我们的数据库:[{"_id" : ObjectId("55c0e5e5511f0a164a581907"),"_class" : "er","name" : "Eric","age" : 45},{"_id" : ObjectId("55c0e5e5511f0a164a581908"),"_class" : "er","name" : "Antony","age" : 55}]现在让我们看一下查询代码:Query query = new Query();query.addCriteria(Criteria.where("name").is("Eric"));List<User> users = mongoTemplate.find(query, User.class);该逻辑的返回值将如预期:{"_id" : ObjectId("55c0e5e5511f0a164a581907"),"_class" : "er","name" : "Eric","age" : 45}2.2. 正则表达式正则表达式是一种更灵活、更强大的查询类型。
MongoDB–SpringDataMongoDB详细操作(增删改查)在NoSQL盛⾏的时代,App很⼤可能会涉及到MongoDB数据库的使⽤,⽽也必须学会在Spring boot使⽤Spring Data连接MongoDB进⾏数据增删改查操作,如下为详细的操作⼿册。
依赖直接导⼊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>属性⽂件application.properties#mongodb连接地址,集群⽤“;”隔开spring.mongo.mongoDatabaseAddress=10.110.112.165:27092;10.110.112.166:27092#mongo数据名spring.mongo.dbname=mongodb#mongo⽤户ername=mongodbopr#mongo密码spring.mongo.password=123456#mongo最⼤连接数spring.mongo.connectionsPerHost=50mongoDB 配置注册Mongo实例配置:@Configurationpublic class MongodbConfig {public static final String COMMA = ";";public static final String COLON = ":";@Value("${spring.mongo.mongoDatabaseAddress}")private String mongoDatabaseAddress;@Value("${ername}")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*/@Beanpublic 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;}}mongoDB操作使⽤MongoTemplate类进⾏增删改查@Servicepublic class MongodbService {@Autowiredprivate 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.cl ass);}/*** 查询⽂档* @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包含错误,则可以⽅便地记录或引发异常。
Mongodb系列-spring-data-mongodb使⽤MongoTemplate实。
在⽤spring-data-mongodb框架开发的过程中,需要实现分页查询,就百度了下,没找到满意的⼜google了下,找到了思路.在spring-data-mongodb 官⽅⽂档中,建议你使⽤PagingAndSortingRepository 来实现分页,但是我是真的不喜欢这个设计啊!!⽤⽅法名来映射查询语句,框架会⾃动⽣成执⾏代码,还为此定义了⼀套语法,举个例⼦:public interface UserRepository extends MongoRepository<User, String>, QueryDslPredicateExecutor<User> {@Query("{ 'name' : ?0 }")List<User> findUsersByName(String name);@Query("{ 'age' : { $gt: ?0, $lt: ?1 } }")List<User> findUsersByAgeBetween(int ageGT, int ageLT);List<User> findByName(String name);List<User> findByNameLikeOrderByAgeAsc(String name);List<User> findByAgeBetween(int ageGT, int ageLT);@Query(value = "{}", fields = "{name : 1}")List<User> findNameAndId();@Query(value = "{}", fields = "{_id : 0}")List<User> findNameAndAgeExcludeId();}这个接⼝类只定义了接⼝,并不需要实现,因为SDM框架(spring-data-mongodb简称,以下都使⽤简称)会帮你⽣成代码..findByAgeBetween(int ageGT, int ageLT);-> 就是where ageGT <age and age <ageLT;刚开始可能感觉很简单,但是⼀旦字段多了查询条件复杂了! 你根本不知道⾃⼰在写什么!别⼈看你的代码⼀长串⽅法名,也是直接懵逼的..⽽查出来的许多分页查询也是直接使⽤的PagingAndSortingRepository 这个接⼝,⾃动⽣成...⾮常不喜欢...就去查怎么使⽤MongoTemplate实现...先下班....放假回来补上..哈哈庆祝五⼀上班,把没写的写完...使⽤MongoTemplate实现分页@Repository("deviceStatusRepository")public class DeviceStatusRepository {@Autowiredprivate MongoOperations mongoOperations;/*** 分页查询*/public PageImpl<DeviceStatusItem> pageDeviceStatusItemByDeviceSerial(String deviceSerial, String collectionName,int pageIndex, int pageSize) {Query query = Query.query(Criteria.where(CONSTS.DEVICE_SERIAL_FIELD).is(deviceSerial));// 每页五个Pageable pageable = new PageRequest(pageIndex, pageSize); // get 5 profiles on a pagequery.with(pageable);// 排序query.with(new Sort(Direction.ASC, CONSTS.DEVICE_SERIAL_FIELD, CONSTS.DOMAINID_FIELD));// 查询总数int count = (int) mongoOperations.count(query, DeviceStatusItem.class, collectionName);List<DeviceStatusItem> items = mongoOperations.find(query, DeviceStatusItem.class, collectionName);// System.out.println("stories:" + stories.size() + " count:" + count);return (PageImpl<DeviceStatusItem>) PageableExecutionUtils.getPage(items, pageable, () -> count);}}解析:MongoOperations 是MongoTemplate的接⼝,它的具体实现就是MongoTemplate,所以这⾥使⽤MongoTemplate或MongoOperations 都可以.1. 创建PageRequest 对象,这是SDM框架提供的现成的分页请求类.构造函数很简单:// page:第⼏页, size:每页的⼤⼩public PageRequest(int page, int size) {this(page, size, null);}2. 构建Query 查询条件.我这⾥先是指定了根据序列号查询,然后设置分页请求 query.with(pageable);最后设置结果的排序.3. 使⽤SDM框架⾃带的⼯具类PageableExecutionUtils 返回PageImpl .这⾥的PageableExecutionUtils 和PageImpl 其实都可以⾃⼰实现,你可以打开PageImpl 看⼀下代码很简单,就是对查询结果封装了下,⽅便数据的返回.调⽤⽅法:1// 序列号2 String deviceSerial="123456";3//集合的名字,就相当于表名4 String cllectionName="device";5//返回第⼏页6int pageIndex = 0;7//每页的⼤⼩8int pageSize = 10;9 PageImpl<DeviceStatusItem> pageImpl = deviceStatusRepository10 .pageDeviceStatusItemByDeviceSerial(deviceSerial, collectionName, pageIndex, pageSize);11 System.out.println("list:" + pageImpl.getContent() + " number:" + pageImpl.getNumber() + " size:"12 + pageImpl.getSize() + " pages:" + pageImpl.getTotalPages()13 + " TotalElements:" + pageImpl.getTotalElements());解析: 这个PageImpl ⽅法名很清晰了.查询的结果集: pageImpl.getContent(),当前页是第⼏个: pageImpl.getNumber()当前页的⼤⼩: pageImpl.getSize()⼀共多少页: pageImpl.getTotalPages()⼀共多少条记录: pageImpl.getTotalElements()优化的分页实现使⽤上边的分页实现没有⼤的问题, 但是有⼀个性能问题, 当你的集合很⼤的时候, count每次执⾏都会全表扫描⼀下,因为你只有全表扫描才知道有多少数量,耗费很多时间.⽽这个时间是没有必要的.你优化的实现就是去掉count,就想下边这样:/*** deviceSerials分页查询,不使⽤count,不然每次都要全表扫描.*/public PageImpl<DeviceStatusItem> pageDeviceStatusItemByDeviceSerialListNotCount(List<String> deviceSerials,String collectionName, int pageIndex, int pageSize) {Query query = Query.query(Criteria.where(CONSTS.DEVICE_SERIAL_FIELD).in(deviceSerials));// 每页五个Pageable pageable = new PageRequest(pageIndex, pageSize); // get 5 profiles on a pagequery.with(pageable);// 排序query.with(new Sort(Direction.ASC, CONSTS.DEVICE_SERIAL_FIELD, CONSTS.DOMAINID_FIELD));List<DeviceStatusItem> items = readMongoTemplate.find(query, DeviceStatusItem.class, collectionName);// System.out.println("stories:" + stories.size() + " count:" + count);return (PageImpl<DeviceStatusItem>) PageableExecutionUtils.getPage(items, pageable, () -> 0);}把count去掉就好.这样去掉count后, 只有在最后⼀次查询时才会进⾏全表扫描.使⽤count和不使⽤count性能⽐较1.准备数据:准备了50万数据,不是很多,就简单测试下, 数据量越⼤效果越明显.2.测试程序只列了主要的程序:public static void readUseCount(IDeviceShadowQueryService deviceShadowQueryService, List<String> deviceSerials) { int pageIndex = 0;int pageSize = 80;int totalPages = 0;Pagination<DeviceStatusDto> pagination = deviceShadowQueryService.readDeviceStatusDtoByDeviceSerials(deviceSerials, pageIndex, pageSize);int size = pagination.getRecords().size();totalPages = pagination.getTotalPages();// 第1页开始for (int i = 1; i < totalPages; i++) {pagination = deviceShadowQueryService.readDeviceStatusDtoByDeviceSerials(deviceSerials, i, pageSize);totalPages = pagination.getTotalPages();size = pagination.getRecords().size();}count++;if (count % 100 == 0)System.out.println("totalPages:" + totalPages + " size:" + size);}public static void readNoCount(IDeviceShadowQueryService deviceShadowQueryService, List<String> deviceSerials) { int pageIndex = 0;int pageSize = 80;Pagination<DeviceStatusDto> page = deviceShadowQueryService.readDeviceStatusDtoByDeviceSerialsList(deviceSerials, pageIndex, pageSize);int size = page.getRecords().size();while (size == pageSize) {pageIndex++;page = deviceShadowQueryService.readDeviceStatusDtoByDeviceSerialsList(deviceSerials, pageIndex, pageSize); size = page.getRecords().size();}count++;if (count % 100 == 0)System.out.println("pageIndex:" + pageIndex + " size:" + size);}3.测试结果使⽤count,开始读取, ⼤⼩:99975使⽤count,读取完毕,⼤⼩:99975 花费时间:112792不使⽤count,读取完毕,⼤⼩:99975 花费时间:109696不使⽤count,节约时间: 112792-109696=2900= 2.9s参考:。
springdatamongodb操作xml配置(mongo集群⽅式):<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xmlns:mongo="/schema/data/mongo"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans.xsd/schema/context/schema/context/spring-context-3.0.xsd/schema/data/mongo/schema/data/mongo/spring-mongo.xsd"><!--credentials的配置形式是:⽤户名:密码@默认数据库--><!-- credentials="${ername}:${mongo.password}@${mongo.dbname}" --><mongo:mongo-client id="mongoClient" replica-set="${mongo.replica.set.address}"><mongo:client-optionsconnections-per-host="${mongo.connections_per_host}"threads-allowed-to-block-for-connection-multiplier="${mongo.threads_allowed_to_block_for_connection_multiplier}" connect-timeout="${mongo.connect_timeout}"max-wait-time="${mongo.max_wait_time}"socket-timeout="${mongo.socket_timeout}"/></mongo:mongo-client><mongo:db-factory id="mongoDbFactory" dbname="${mongo.dbname}" mongo-ref="mongoClient" /><!--⾸先列⼀下WriteConcern的⼏种抛出异常的级别参数:WriteConcern.NONE:没有异常抛出WriteConcern.NORMAL:仅抛出⽹络错误异常,没有服务器错误异常WriteConcern.SAFE:抛出⽹络错误异常、服务器错误异常;并等待服务器完成写操作。
springdatamongodb五:进阶文档查询(分页morphia)(二)
Spring Data MongoDB 三:基本文档查询(Query、BasicQuery)(一)
学习MongoDB 六:MongoDB查询(游标操作、游标信息)(三)
一.简介
SpringData MongoDB提供了
org.springframework.data.mongodb.core.MongoTemplate对MongoDB的find的操作,我们上一篇介绍了基本文档的查询,我们今天介绍分页查询,分页查询是返回到匹配文档的游标,可以随意修改查询限制、跳跃、和排序顺序的功能。
我们在查询时find()方法接受Query类型有
org.springframework.data.mongodb.core.query和
org.springframework.data.mongodb.core.query.BasicQuery Query类提供方法有limit、skip、sort查询限制、跳跃、和排序顺序的功能,BasicQuery继承了Query类。
Query
Mongodb
说明Query limit (int limit)
limit
方法是限制游标返回结果的数量Query skip (int skip)
skip
方法可以跳过指定值的条数,返回剩下的条数的结果,可以跟limit()方法进行组合可以实现分页的效果Sort sort () 已过时
现在是用query.with(sort)
sort
方法来对数据进行排序,根据指定的字段,并使用1或-1来指定排序方式是升序或降序,类似于SQL的order by。
SpringDataMongoDB三:基本⽂档查询(Query、BasicQuery)(⼀)⼀.简单介绍Spring Data MongoDB提供了org.springframework.data.mongodb.core.MongoTemplate对MongoDB的CRUD的操作,上⼀篇我们介绍了对MongoDB的新增和删除,今天我们要介绍Java代码实现对MongoDB实现查询操作。
我们回想⼀下。
我们在之前介绍了MongoDB的基本⽂档查询,MongoDB的查询语法:db.orders.find({{<field1>:<value1>,<field2>: <value2>, ... } },{field1:<boolean>, field2: <boolean> ... })我们介绍是SpringData MongoDB 提供了find⽅法。
⽅便我们通过java代码实现对MongoDB的查询操作:mongoTemplate.find (query, entityClass)參数说明:entityClass:实体class,也就是要把⽂档转换成相应的实体。
query查询语句的实现的⽅式有两种:.springframework.data.mongodb.core.query构造函数Query (Criteria criteria)接受的參数是org.springframework.data.mongodb.core.query.CriteriaCriteria是标准查询的接⼝,能够引⽤静态的Criteria.where的把多个条件组合在⼀起,就能够轻松地将多个⽅法标准和查询连接起来,⽅便我们操作查询语句。
⽐如:查询条件onumber="002"mongoTemplate.find (new Query(Criteria.where("onumber").is("002")),entityClass)多个条件组合查询时:⽐如:onumber="002" and cname="zcy"mongoTemplate.find (new Query(Criteria.where("onumber").is("002").and("cname").is("zcy")),entityClass)⽐如:onumber="002" or cname="zcy"mongoTemplate.findOne(newQuery(newCriteria().orOperator(Criteria.where("onumber").is("002"),Criteria.where("cname").is("zcy"))),entityClass);我们通过Criteria的and⽅法,把这个条件组合⼀起查询Criteria提供了⾮常多⽅法,我们这边先介绍基本⽂档的查询操作符。
Spring-data-mongodb使用手册文档信息(Document Info)标题(Title)Spring-data-mongodb使用手册文档编号(No)2012-09-19作者(Author)张瑜最后发布时间(Last Update)2012-09-20概述(Summarize)安装mongodb以及掌握spring-data-mongodb的使用方法,一些最佳实践修订信息(Revise Info)修订日期(Date)修订人(Reviser) 修订内容(Revises)附件信息(Attachment Info)目录文档信息(Document Info) (2)修订信息(Revise Info) (3)附件信息(Attachment Info) (4)1.概述 (5)1.1.目的 (5)1.2.范围 (6)2.准备 (6)2.1.环境配置 (6)2.2.Windows7安装mongodb (6)2.2.1.配置环境变量 (6)2.2.2.启动配置mongodb (7)3.Spring-data-mongodb (8)3.1.背景 (8)3.1.1.高级API (9)3.1.2.低级API (9)3.2.MongoDbFactory (9)3.3.MongoTemplate (9)3.4.Operations (10)3.4.1.常用Api的方法: (10)3.5.项目中如何配置实用mongodb (11)3.6.Callback .................................................................................. 错误!未定义书签。
3.7.Topic和Messaging/PubSub (14)3.8.Cache (14)4.NoSQL数据库设计 (14)4.1.案例1 (14)5.最佳实践 (14)5.1.项目案例1(Tinybee项目) (14)1.概述1.1. 目的让团队成员比较快的上手mongodb的相关功能,思考如何结合自己的项目使用。
SpringData-MongoTemplate的基本使⽤⽅法SpringData - MongoTemplate的基本使⽤⽅法描述语法⼀个条件(等)queryByName(String name)⼆个条件(且)queryByNameAndAge(String name, Integer age)⼆个条件(或)queryByNameOrAge(String name, Integer age)2数之间(不包含2数)queryByAgeBetween(Integer min, Integer max) =={ "age" : { "$gt" : 13, "$lt" : 30}} <queryByAgeLessThan(Integer age)<=queryByAgeLessThanEqual(Integer age)>queryByAgeGreaterThan(Integer age);>=queryByAgeGreaterThanEqual(Integer age);After = >queryByAgeGreaterThan(Integer age);Beftore = <queryByAgeLessThan(Integer age)判断空findByNameIsNull判断不为空findByNameIsNotNulllike findByNameLikeNotLike findByNameNotLikeStartingWith findByNameStartingWithEndingWith findByNameEndingWithContaining findByNameContaining查询排序findByIdOrderByName[Desc Asc]not findByNameNotIn findByIdInNotin findByIdNotInTrue findByStatusTrueFalse findByStatusFalse查询字段并排序findByIshotOrderBySequenceIgnoreCase(忽略⼤⼩写)queryByNameIgnoreCaseQueryCriteriaQuery query = new Query();Criteria criteria = Criteria.where("name").is("will");mongoTemplate.find(query, User.class);Query增加query.skip(3);query.limit(3);Sort id = Sort.by(Sort.Direction.DESC, "id");query.with(id);Criteria条件Criteria criteria = new Criteria(); Criteria criteria1 = criteria.orOperator( Criteria.where("name").is("dafei"), Criteria.where("age").lt(30) );query.addCriteria(criteria1);正则模糊查询Query query = new Query();String pattern = String.format("^da");Criteria criteria = new Criteria();String zz = String.format("^fei"); Criteria criteria1 = criteria.andOperator( Criteria.where("name").regex(pattern, "m"), Criteria.where("age").lt(30) );query.addCriteria(criteria1);。
spring-data-mongodb常⽤的注解spring-data-mongodb 常⽤的注解@Documentorg.springframework.data.mongodb.core.mapping.Document.class把⼀个java类声明为mongodb的⽂档,可以通过collection参数指定这个类对应的⽂档。
@Document(collection="mongodb 对应 collection 名")// 若未加 @Document ,该 bean save 到 mongo 的 user collection// 若添加 @Document ,则 save 到 reUser collection@Document(collection="reUser")public class User{}@Indexedorg.springframework.data.mongodb.core.index.Indexed.class声明该字段需要索引,建索引可以⼤⼤的提⾼查询效率。
@CompoundIndexpoundIndex.class复合索引的声明,建复合索引可以有效地提⾼多字段的查询效率。
@Fieldorg.springframework.data.mongodb.core.mapping.Field.class给映射存储到 mongodb 的字段取别名在 java bean 中字段名为 firstName,存储到 mongo 中 key 为 fName@Field("fName")private String firstName;@Idorg.springframework.data.annotation.Id.class⽂档的唯⼀标识,在mongodb中为ObjectId,它是唯⼀的@Transientorg.springframework.data.annotation.Transient.class默认情况下所有的私有字段都映射到⽂档,该注解标识的字段从存储在数据库中的字段列中排除(即该字段不保存到 mongodb)。
SpringDataMongoDB⼀:⼊门篇(环境搭建、简单的CRUD操作)⼀.简介Spring Data MongoDB 项⽬提供与MongoDB⽂档数据库的集成。
Spring Data MongoDB POJO的关键功能区域为中⼼的模型与MongoDB的DBCollection轻松地编写⼀个存储库交互数据访问。
⼆.Spring Data MongoDB的配置以及下载对应的Jar1.安装MongoDb数据库,我们在上⼀篇就已经介绍过了,这边就不在介绍了,2.下载spring的spring-data的⼦项⽬两个jar,分别是spring-data-commons和spring-data-mongodb我这边下载是两个jar分别是:spring-data-commons-1.7.2.RELEASE.jarspring-data-mongodb-1.4.2.RELEASE.jar3.下载mongoDb的java驱动jar包这边有很多版本,下载⾃⼰对应得版本,我下载是:mongo-java-driver-2.9.3.jar4.⽤Java测试⼀下MongoDB是否能正常连接[java]1. public class TestMongodb {2. @Test3. public void testMongodb()4. {5. try{6. // 连接到 mongodb 服务7. Mongo mongo = new Mongo("127.0.0.1", 27017);8. //根据mongodb数据库的名称获取mongodb对象 ,9. DB db = mongo.getDB( "test" );10. Set<String> collectionNames = db.getCollectionNames();11. // 打印出test中的集合12. for (String name : collectionNames) {13. System.out.println("collectionName==="+name);14. }15.16. }catch(Exception e){17. e.printStackTrace();18. }运⾏能获取test数据库下的集合,说明能正常连接数据库5.Spring的配置⽂件1)applicationContext-mongo.xml[html]1. <?xml version="1.0" encoding="UTF-8"?>2. <beans xmlns="/schema/beans"3. xmlns:xsi="/2001/XMLSchema-instance" xmlns:aop="/schema/aop"4. xmlns:tx="/schema/tx" xmlns:util="/schema/util"5. xmlns:context="/schema/context" xmlns:mongo="/schema/data/mongo"6. xsi:schemaLocation="/schema/beans /schema/beans/spring-beans-3.0.xsd7. /schema/aop /schema/aop/spring-aop-3.0.xsd8. /schema/tx /schema/tx/spring-tx-3.0.xsd9. /schema/util /schema/util/spring-util-3.0.xsd10. /schema/data/mongo /schema/data/mongo/spring-mongo-1.0.xsd11. /schema/context /schema/context/spring-context-3.0.xsd">12. <context:component-scan base-package="com.mongo" />13. <!-- 获取配置资源 -->14. <context:property-placeholder location="classpath:jdbc.properties" />15.16. <bean class="cn.mongo.util.SpringContextUtil"></bean>17.18. <mongo:mongo id="mongo" replica-set="${mongo.replicaSet}">19. <!--20. connections-per-host: 每个主机答应的连接数(每个主机的连接池⼤⼩),当连接池被⽤光时,会被阻塞住21. max-wait-time: 被阻塞线程从连接池获取连接的最长等待时间(ms)22. connect-timeout:在建⽴(打开)套接字连接时的超时时间(ms)23. socket-timeout:套接字超时时间;该值会被传递给Socket.setSoTimeout(int)24. slave-ok:指明是否答应驱动从次要节点或者奴⾪节点读取数据25. -->26. <mongo:options27. connections-per-host="${mongo.connectionsPerHost}"28. threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}"29. connect-timeout="${mongo.connectTimeout}"30. max-wait-time="${mongo.maxWaitTime}"31. auto-connect-retry="${mongo.autoConnectRetry}"32. socket-keep-alive="${mongo.socketKeepAlive}"33. socket-timeout="${mongo.socketTimeout}"34. slave-ok="${mongo.slaveOk}"35. write-number="${mongo.writeNumber}"36. write-timeout="${mongo.riteTimeout}"37. write-fsync="${mongo.writeFsync}"/>38. </mongo:mongo>39. <!-- 设置使⽤的数据库名-->40. <mongo:db-factory dbname="test" mongo-ref="mongo"/>41. <!-- mongodb的模板 -->42. <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">43. <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>44. </bean>45. </beans>2)jdbc.properties[html]1. mongo.replicaSet=127.0.0.1:270172. mongo.connectionsPerHost=83. mongo.threadsAllowedToBlockForConnectionMultiplier=44. mongo.connectTimeout=10005. mongo.maxWaitTime=15006. mongo.autoConnectRetry=true7. mongo.socketKeepAlive=true8. mongo.socketTimeout=15009. mongo.slaveOk=true10. mongo.writeNumber=111. mongo.riteTimeout=012. mongo.writeFsync=true说明:三.Spring 实现MongoDB的CRUD操作1.实现⼀个基础接⼝,是⽐较通⽤的 MongoBase.java类[java]1. public interface MongoBase<T> {2. //添加3. public void insert(T object,String collectionName);4. //根据条件查找5. public T findOne(Map<String,Object> params,String collectionName);6. //查找所有7. public List<T> findAll(Map<String,Object> params,String collectionName);8. //修改9. public void update(Map<String,Object> params,String collectionName);10. //创建集合11. public void createCollection(String collectionName);12. //根据条件删除13. public void remove(Map<String,Object> params,String collectionName);14.15. }2.实现⼀个实体类,我这边实现了User类@Document注解,表⽰这个POJO最终要持久化为MongoDB中的document[java]1. @Document2. public class User implements Serializable {3. /**4. *5. */6. private static final long serialVersionUID = 1L;7. private String id;8. private String name;9. private int age;10. private String password;11.12. public String getName() {13. return name;14. }15. public void setName(String name) {16. = name;17. }18. public int getAge() {19. return age;20. }21. public void setAge(int age) {22. this.age = age;23. }24. public String getPassword() {25. return password;26. }27. public void setPassword(String password) {28. this.password = password;29. }30. public String getId() {31. return id;32. }33. public void setId(String id) {34. this.id = id;35. }36.37.38.39. }3.实现UserDao类,就是实现User⾃⼰操作数据库的接⼝,这个UserDao也继承了MongoBase接⼝,我们这边UserDao没实现其他额外的接⼝[java]1. public interface UserDao extends MongoBase<User>{2.3. }4.实现UserDaoImpl具体类,这边是实际操作数据库[java]1. @Repository("userDaoImpl")2. public class UserDaoImpl implements UserDao {3.4. @Resource5. private MongoTemplate mongoTemplate;6.7. @Override8. public void insert(User object,String collectionName) {9. mongoTemplate.insert(object, collectionName);10. }11.12. @Override13. public User findOne(Map<String,Object> params,String collectionName) {14. return mongoTemplate.findOne(new Query(Criteria.where("id").is(params.get("id"))), User.class,collectionName);15. }16.17. @Override18. public List<User> findAll(Map<String,Object> params,String collectionName) {19. List<User> result = mongoTemplate.find(new Query(Criteria.where("age").lt(params.get("maxAge"))), User.class,collectionName);20. return result;21. }22.23. @Override24. public void update(Map<String,Object> params,String collectionName) {25. mongoTemplate.upsert(new Query(Criteria.where("id").is(params.get("id"))), new Update().set("name", params.get("name")), User.class,collectionName);26. }27.28. @Override29. public void createCollection(String name) {30. mongoTemplate.createCollection(name);31. }32.33.34. @Override35. public void remove(Map<String, Object> params,String collectionName) {36. mongoTemplate.remove(new Query(Criteria.where("id").is(params.get("id"))),User.class,collectionName);37. }说明:mongoTemplate.upsert这边update⾥⾯提供了很多功能,可以根据条件进⾏修改,Criteria这个类也提供了where 、and、lt等,我们在查询年龄⼤于30的查出来,mongoTemplate.find(new Query(Criteria.where("age").lt(params.get("maxAge"))), User.class,collectionName);Criteria还很多如图所⽰:4.实现测试类我们这边为了节省时间,就没写服务类,我们直接调⽤dao就可以了,实现了TestUser.java类1)添加并根据条件查找列表[java]1. public class TestUser {2.3. private static UserDao userDaoImpl;4. private static ClassPathXmlApplicationContext app;5. private static String collectionName;6. @BeforeClass7. public static void initSpring() {8. try {9. app = new ClassPathXmlApplicationContext(new String[] { "classpath:applicationContext-mongo.xml",10. "classpath:spring-dispatcher.xml" });11. userDaoImpl = (UserDao) app.getBean("userDaoImpl");12. collectionName ="users";13. } catch (Exception e) {14. e.printStackTrace();15. }16. }17.18. @Test19. public void testAdd()20. {21.22. //添加⼀百个user23. for(int i=0;i<100;i++){24. User user =new User();25. user.setId(""+i);26. user.setAge(i);27. user.setName("zcy"+i);28. user.setPassword("zcy"+i);29. userDaoImpl.insert(user,collectionName);30. }31. Map<String,Object> params=new HashMap<String,Object>();32. params.put("maxAge", 50);33. List<User> list=userDaoImpl.findAll(params,collectionName);34. System.out.println("user.count()=="+list.size());35. }运⾏⼀下,我们能正常查找年龄⼤于50的2)根据ID进⾏修改[java]1. @Test2. ublic void testUdate(){3. Map<String,Object> params=new HashMap<String,Object>();4. params.put("id", "1");5. User user=userDaoImpl.findOne(params, collectionName);6. System.out.println("==="+user.getName());7. System.out.println("=============update==================");8. params.put("name", "hello");9. userDaoImpl.update(params, collectionName);10. user=userDaoImpl.findOne(params, collectionName);11. System.out.println("==="+user.getName());3)根据ID删除对应的数据[java]1. @Test2. ublic void testRemove(){3. Map<String,Object> params=new HashMap<String,Object>();4. params.put("id", "2");5. userDaoImpl.remove(params, collectionName);6. User user=userDaoImpl.findOne(params, collectionName);7. System.out.println("user=="+user);。
Spring使⽤MongoDB 1. 准备集成环境,添加依赖<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.3.RELEASE</version></parent><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--spring boot data mongodb--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>2. 配置连接参数(application.properties)# application.properties# 配置数据库连接#格式: mongodb://账号:密码@ip:端⼝/数据库?认证数据库spring.data.mongodb.uri=mongodb://root:admin@localhost/mongotest?authSource=admin# 配置MongoTemplate的执⾏⽇志.springframework.data.mongodb.core=debug3. domain 代码说明 @AllArgsConstructor@NoArgsConstructor@Setter@Getter@ToString@Document("users") //设置⽂档所在的集合public class User {@Id //⽂档的id使⽤ObjectId类型来封装,并且贴上@Id注解private ObjectId _id;private Long id;private String name;private Integer age;}MongoDBRePository接⼝/*** ⾃定义⼀个接⼝继承MongoRepository,* 泛型1:domain类型* 泛型2:⽂档主键类型* 贴上@Repository注解,底层会创建出动态代理对象,交给Spring管理*/@Repositorypublic interface UserMongoRepository extends MongoRepository<User, ObjectId> {// 使⽤Spring Data命名规范做⾼级查询List<User> findByName(String name);}关于⾃定义⽅法的JPA规范 4. 实例代码:@Autowiredprivate UserMongoRepository repository;// 插⼊/更新⼀个⽂档@Testpublic void testSaveOrUpdate() throws Exception {User user = new User(null, 5L, "bunny", 20);// 主键为null则新增,不为null则更新repository.save(user);}// 删除⼀个⽂档@Testpublic void testDelete() throws Exception {repository.deleteById(new ObjectId("xxx"));}// 查询⼀个⽂档@Testpublic void testGet() throws Exception {Optional<User> optional = repository.findById(new ObjectId("xxx"));optional.ifPresent(System.err::println);}// 查询所有⽂档@Testpublic void testList() throws Exception {// 查询所有⽂档List<User> list = repository.findAll(); list.forEach(System.err::println);} 5.MongoDBTemplate。
Spring Data MongoDB 简介Spring Data MongoDB 简介1. 概述本文将对进行快速实用的Spring Data MongoDB 介绍。
我们将使用MongoTemplate 和MongoRepository 的基础知识来实际测试说明每个操作。
2. MongoTemplate 和MongoRepositoryMongoTemplate 遵循Spring 的标准模板模式,并提供一个到底层持久化引擎的准备好的、基础的API。
repository 遵循Spring 以数据为中心的理念,并基于所有Spring Data 项目中众所周知的访问模式,提供更灵活、更复杂的API 操作。
对于这两者,我们需要首先定义依赖项——举个例子,在pom.xml 中,使用Maven:<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-mongodb</artifactId><version>1.10.4.RELEASE</version></dependency>要检查是否有任何新版本的库发布,请在此处追踪版本。
3. MongoTemplate 的配置3.1. XML 配置让我们从MongoTemplate 的简单XML 配置开始:<mongo:mongo id="mongo" host="localhost" /><mongo:db-factory id="mongoDbFactory" dbname="test" mongo-ref="mongo" />首先,我们需要定义负责创建Mongo 实例的工厂bean。
SpringDataMongoDB数据库批量操作的⽅法前⾔在项⽬开发中遇到了需要批量插⼊数据和更新数据的操作,但是在某度上搜并没有找到有⽤的东西,于是到stackoverflow中搜到如下解决⽅案:实践⼀、BulkOperations 批量插⼊代码如下:testModel m1 = new testModel("m1", 10);testModel m2 = new testModel("m2", 20);// BulkMode.UNORDERED:表⽰并⾏处理,遇到错误时能继续执⾏不影响其他操作;BulkMode.ORDERED:表⽰顺序执⾏,遇到错误时会停⽌所有执⾏ BulkOperations ops = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, "test");ops.insert(m1);ops.insert(m2);// 执⾏操作ops.execute();运⾏结果:成功插⼊多条数据。
⼆、BulkOperations 批量更新代码如下:Update u1 = new Update().set("age",15);Query q1 = new Query(Criteria.where("name").is("m1"));Update u2 = new Update().set("age",25);Query q2 = new Query(Criteria.where("name").is("m2"));BulkOperations ops = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, "test"); ops.updateOne(q1,u1);ops.updateOne(q2,u2);ops.execute();运⾏结果:成功更新多条数据。
SpringDataMongoDB多⽂档事务的实现⼀、安装MongoDB4.0.3(××)1.1、官⽅安装⽂档1.2、tar.gz包下载地址1.3、复制集官⽅配置⼆、SpringProject版本依赖(×)Spring:5.1.1.RELEASE 以上SpringDataMongoDB:2.1.1.RELEASE 以上三、配置MongoTransactionManager(SpringBoot使⽤⽅式)SpringBoot 集成⾮常简单,配置MongoTransastionManager,⽬前Spring-boot-starter-data-mongodb 版本较低不⽀持,因此暂未验证,SpringBoot配置复制集参考SpringBoot相关⽂档@Configurationstatic class Config extends AbstractMongoConfiguration {@BeanMongoTransactionManager transactionManager(MongoDbFactory dbFactory) {return new MongoTransactionManager(dbFactory);}// ...}四、配置MongoTransactionManager(普通Spring项⽬)<context:property-placeholder location="classpath:mongo.properties" ignore-unresolvable="true"file-encoding="utf-8" /><!--重点配置1.安全配置:credentials="${er}:${mongo.password}@${mongo.database}"2.单机配置:host="${mongo.host}" port="${mongo.port}"3.副本集配置:replica-set="${mongo.replSet}"--><mongo:mongo-client id="mongoClient" replica-set="${mongo.replSet}"><mongo:client-options min-connections-per-host="${mongo.minConnectionsPerHost}"write-concern="SAFE"read-preference="NEAREST"threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}"connect-timeout="${mongo.connectTimeout}" max-wait-time="${mongo.maxWaitTime}"socket-keep-alive="${mongo.socketKeepAlive}" socket-timeout="${mongo.socketTimeout}"max-connection-idle-time="${mongo.maxConnectionIdleTime}"max-connection-life-time="${mongo.maxConnectionLifeTime}"heartbeat-socket-timeout="${mongo.heartbeatSocketTimeout}"heartbeat-connect-timeout="${mongo.heartbeatConnectTimeout}"min-heartbeat-frequency="${mongo.minHeartbeatFrequency}"heartbeat-frequency="${mongo.heartbeatFrequency}" /></mongo:mongo-client><mongo:db-factory id="mongoDbFactory" dbname="${mongo.database}"mongo-ref="mongoClient" /><bean id="mappingContext"class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" /><bean id="defaultMongoTypeMapper"class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper"><constructor-arg name="typeKey"><null /></constructor-arg></bean><bean id="mappingMongoConverter"class="org.springframework.data.mongodb.core.convert.MappingMongoConverter"><constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /><constructor-arg name="mappingContext" ref="mappingContext" /><property name="typeMapper" ref="defaultMongoTypeMapper" /></bean><bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"><constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /><constructor-arg name="mongoConverter" ref="mappingMongoConverter" /></bean><!-- 重点配置 --><bean id="mongoTransactionManager" class="org.springframework.data.mongodb.MongoTransactionManager"> <constructor-arg name="dbFactory" ref="mongoDbFactory"/></bean><tx:annotation-driven transaction-manager="mongoTransactionManager" proxy-target-class="true"/>五、使⽤事务(×)@Servicepublic class StateService {@Autowiredprivate MongoTemplate teplate;@Transactionalvoid someBusinessFunction(Step step) {template.insert(step);log.debug(1/0);};});六、Mongo.properties 配置mongo.host=192.168.1.66mongo.port=27017mongo.replSet=192.168.1.66:2000,192.168.1.66:2001,192.168.1.66:2002mongo.minConnectionsPerHost=10mongo.threadsAllowedToBlockForConnectionMultiplier=4mongo.connectTimeout=30000mongo.maxWaitTime=3000mongo.socketKeepAlive=falsemongo.socketTimeout=30000mongo.maxConnectionIdleTime=0mongo.maxConnectionLifeTime=0mongo.heartbeatSocketTimeout=20000mongo.heartbeatConnectTimeout=10000mongo.minHeartbeatFrequency=3000mongo.heartbeatFrequency=5000mongo.database=labsta七、最后是重点(×××××)7.1、必须使⽤复制集,单节点不⽀持,mongodb4.2 会⽀持分⽚集事务,复制集安装请⾃⾏研究7.2、使⽤事务之前(@Transaction),数据库和⽂档必须提前创建,如何解决呢?且看下篇7.3、Spring版本和SpringDataMongodb版本必须遵循 @SpringProject版本依赖7.4、注意,此处的复制集不是4.0版本之前的主从复制集群,4.0之后已废弃主从模式以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
[SpringDataMongoDB]学习笔记--MongoTemplate查询操作查询操作主要⽤到两个类:Query, Criteria所有的find⽅法都需要⼀个query的object。
1. 直接通过json来查找,不过这种⽅式在代码中是不推荐的。
BasicQuery query = new BasicQuery("{ age : { $lt : 50 }, accounts.balance : { $gt : 1000.00 }}");List<Person> result = mongoTemplate.find(query, Person.class);2. 推荐使⽤where + query的⽅式来进⾏查找。
where⽅法⽣成⼀个Criteria对象,然后可以通过调⽤不同的⽅法增加操作符(⽐如lt,gt,and)。
更详细的操作列表请参考import static org.springframework.data.mongodb.core.query.Criteria.where;import static org.springframework.data.mongodb.core.query.Query.query;…List<Person> result = mongoTemplate.find(query(where("age").lt(50).and("accounts.balance").gt(1000.00d)), Person.class);3. MongoDB也⽀持空间查询,⽐如附近的点,下⾯只给出例⼦,详细请看官⽅⽂档。
@Document(collection="newyork")public class Venue {@Idprivate String id;private String name;private double[] location;@PersistenceConstructorVenue(String name, double[] location) {super(); = name;this.location = location;}public Venue(String name, double x, double y) {super(); = name;this.location = new double[] { x, y };}public String getName() {return name;}public double[] getLocation() {return location;}@Overridepublic String toString() {return "Venue [id=" + id + ", name=" + name + ", location="+ Arrays.toString(location) + "]";}}查找圆内的地址Circle circle = new Circle(-73.99171, 40.738868, 0.01);List<Venue> venues =template.find(new Query(Criteria.where("location").withinCenter(circle)), Venue.class);查找球⾯坐标内的地址Circle circle = new Circle(-73.99171, 40.738868, 0.003712240453784);List<Venue> venues =template.find(new Query(Criteria.where("location").withinCenterSphere(circle)), Venue.class);。
spring管理mongodb安装Spring for MongodbSpring项目为方便对Mongodb的操作,建立了spring-data的子项目,地址在:/spring-data/mongodb,目前版本是1.0.0M2阶段,已支持对Mongodb的一系列基本操作。
我们先从/spring-data/mongodb 中下载相关的包:spring-data-document-1.0.0.M2.zip,下载解压后,将解压后的四个JAR 文件放到工程路径的lib库中,本文中还将使用Spring 3.0.4的版本,请读者自行下载配置。
Spring Mongodb的配置目前,可以有两种方式对Spring mongodb进行配置。
第一种是使用Spring 3中的注解,另外一种是使用传统的XML配置。
下面分别进行讲解:使用Spring 3中的注解首先在配置类中,要继承AbstractMongoConfiguration类,代码如下:1.packagecom.mkyong.config;2. importorg.springframework.context.annotation.Bean;3. importorg.springframework.context.annotation.Configuration;4. importorg.springframework.data.document.mongodb.MongoTemplate;5. importorg.springframework.data.document.mongodb.config.AbstractMongoConfiguration;6. importcom.mongodb.Mongo;7./**8. * Spring MongoDB configuration file9. *10.*/11.@Configuration12. publicclassSpringMongoConfig extendsAbstractMongoConfiguration {13.@Override14.public@Bean Mongo mongo() throwsException {15. returnnewMongo("localhost");16. }17.@Override18.public@Bean MongoTemplate mongoTemplate() throwsException {19. returnnewMongoTemplate(mongo(),"yourdb","yourCollection");20. }21. }这里,引入了MongoTemplate模版类,并且使用对连接数据库的地址,数据库名和collection 进行了初始化。
Spring-data-mongodb使用手册文档信息(Document Info)标题(Title)Spring-data-mongodb使用手册文档编号(No)2012-09-19作者(Author)张瑜最后发布时间(Last Update)2012-09-20概述(Summarize)安装mongodb以及掌握spring-data-mongodb的使用方法,一些最佳实践修订信息(Revise Info)修订日期(Date)修订人(Reviser) 修订内容(Revises)附件信息(Attachment Info)目录文档信息(Document Info) (2)修订信息(Revise Info) (3)附件信息(Attachment Info) (4)1.概述 (5)1.1.目的 (5)1.2.范围 (6)2.准备 (6)2.1.环境配置 (6)2.2.Windows7安装mongodb (6)2.2.1.配置环境变量 (6)2.2.2.启动配置mongodb (7)3.Spring-data-mongodb (8)3.1.背景 (8)3.1.1.高级API (9)3.1.2.低级API (9)3.2.MongoDbFactory (9)3.3.MongoTemplate (9)3.4.Operations (10)3.4.1.常用Api的方法: (10)3.5.项目中如何配置实用mongodb (11)3.6.Callback .................................................................................. 错误!未定义书签。
3.7.Topic和Messaging/PubSub (14)3.8.Cache (14)4.NoSQL数据库设计 (14)4.1.案例1 (14)5.最佳实践 (14)5.1.项目案例1(Tinybee项目) (14)1.概述1.1. 目的让团队成员比较快的上手mongodb的相关功能,思考如何结合自己的项目使用。
1.2. 范围所有工程师。
2.准备mongodb 下载地址:/downloadsmongodb 官方文档下载地址:/docs/mongodb-docs-2012-09-19.pdf十天精通mongodb 下载地址(强烈建议看下,其中包含对mongodb的详细介绍):/file/id_45545890496119199.htm如果你对mongodb希望有更多的了解(其中为mongodb资料专题):/html/3548.htmlmongodb管理工具下载地址:/file/id_45545890496119201.htm2.1. 环境配置在这里提供针对windows7 系统的配置方案2.2. Windows7安装mongodbmongodb及其管理工具下载地址参见准备章节!mongodb启动命令参数详见:/jacky0525/blog/330482.2.1.配置环境变量1、在系统环境变量中添加MONGODB_HOME如图所示:2、在PA TH中添加%MONGODB_HOME%\bin 如图所示:在mongodb 目录中新建data 和log 文件夹(为启动时做准备)2.2.2.启动配置mongodb进入DOS命令窗口输入一下命令:mongod --dbpath D:\mongodb\data --logpath D:\mongodb\log --logappend --directoryperdb--dbpath数据库安装目录--logpath 数据库输出目录--logappend 日志追加,默认为覆盖--directoryperdb 表示每个db一个目录执行命令之后开启新的DOS窗口执行mongo 输出表示启动成功。
目前是以无权限限制的方式启动的,你可以做任何操作。
现在我们需要切换到admin下,创建一个root用户。
执行命令:show dbs 显示所有dbuse admin 使用admin dbdb 显示当前使用的dbdb.addUser(”root”,”root”); 添加用户,用户名为root 密码为rootdb.auth(”root”,”root”); 为用户授权这样我们就为admin db创建好用户,接下来以权限限制方式启动mongodb(记得关掉之前开启的服务),执行命令(在之前启动命令中添加参数-auth即可):mongod --dbpath D:\mongodb\data --logpath D:\mongodb\log --logappend --auth–directoryperdb-auth 安全模式下运行接下来使用之前授权的用户名密码登录,打开新的DOS命令窗口输入如下命令:mongo 数据库名称–u 用户名–p 密码mongo admin –u root –p root注意:为了启动方便可以把mongodb加入windows系统service以管理员身份打开DOS命令窗口键入如下命令:mongod --dbpath D:\mongodb\data --logpath D:\mongodb\log --logappend --auth--directoryperdb –install这时候会在系统服务中增加mongo db 项第一次配置完成后,一定要重启才会有效果重启mongo客户端,不输入-u-p可以直接进入,但是不具有任何权限。
3.Spring-data-mongodb3.1. 背景SQL or NoSQL?That’s a question! SQL 与NoSQL 的争论从来没有停息过,但其实任何一种技术都不会是适合一切应用场景的,重要的是你要充分了解自己的需求,再充分了解你要选择的技术的优劣。
优势:快速!(当然,这和具体的应用方式有关,通常来说,它比一般的关系型数据库快5位左右。
)很高的可扩展性–轻轻松松就可实现PB级的存储(但是可能我们并不需要PB级的存储,10TB可能就够了)他有一个很好的replication 模式(replica sets)有很完善的Java API他的存储格式是Json的,这对Java来说非常好处理,对javascirpt亦然。
运维起来非常方便,你不用专门为它安排一个管理员。
它有一个非常活跃的社区。
他的版本控制非常清楚。
MongoDB 背后的公司(10gen)已经准备好了明天在MongoDB 上面的投入的资金。
劣势:应用经验缺乏,我们都没有相关NoSQL 产品的使用经验。
项目相对来说还比较新。
和以往的存储相比,数据的关系性操作不再存在。
常用Jar:spring-data-mongodbmongo-java-driverspring-core相关JAR在MA VEN包管理中搜索选择对应版本即可3.1.1.高级API3.1.2.低级API3.2. MongoDbFactory就像所有的数据库连接,mongoDbFactory就是连接工厂,通过配置单台服务器或者连接池(pool)的方式获取Mongodb服务器的连接。
3.3. MongoTemplate就像Spring提供的JDBC,hibernate和ibatis的template一样,spring-data-mongodb 也提供了一个基础的泛型MongoTemplate供开发者可以快速的利用代码完成基础的crud工作。
在实践中可以考虑完全省去dao层的设计,直接在service层注入相应的template实例。
在此推荐写一个Repository<T>接口其中提供对mongodb的CRUD操作。
3.4. Operations其实所有的操作都是直接映射Mongodb本身提供的命令行,Spring-data-mongodb 文档来操作。
官网提供的API Javadoc有问题报404,只能看HTML版的参考手册:/spring-data/data-mongodb/docs/current/reference/html/ 404问题修复了(官方API):/spring-data/data-mongodb/docs/current/apidocs/3.4.1.常用Api的方法:新增方法:User user = new User("...");//将user对象保存到"user"这个collection中mongoTemplate.save(user);//将user对象保存到"new collection"这个collection中mongoTemplate.save("new collection",user);//将user对象保存到"user"这个collection中mongoTemplate.insert(user);//将user对象保存到"new collection"这个collection中mongoTemplate.insert("new collection", user);//将user的对象列表(List)保存到"user"collection中去mongoTemplate.insertList(userInList);//将user的对象列表(List)保存到"new collection"collection中去mongoTemplate.insertList("new collection", userInList);另外请注意其中的save和insert的区别。
它们的区别为:1)save意思是,当记录不存在时插入,或者是当记录已存在是更新,实际上就是save or update的意思。
2) insert的意思是:当记录不存在时插入,而如果记录存在时则忽略,继续插入。
查询方法://创建查询条件id = 123 和name = zhangyuQuery query = new Query(Criteria.where("id").is(123).and("name").is("zhangyu"));//执行查询返回结果List<User> user = mongoTemplate.find(query, User.class);//创建查询条件id <= 123 和name = zhangyuQuery query = new Query(Criteria.where("id").lte(123).and("name").is("zhangyu"));删除方法:User user = new User("...");//删除user集合中的user对象mongoOperation.remove(user);//删除test集合下的id=2的user对象mongoOperation.remove("test", new Query(Criteria.where("id").is("2")));//删除test集合下的,id=3的user对象,最后并且返回这个被删除的对象User deletedUser = mongoOperation.findAndRemove("test",new Query(Criteria.where("id").is("3")), User.class);3.5. 项目中如何配置实用mongodb配置文件如图所示:之后通过注解注入mongoTemplate 即可3.6. 基于实体Bean操作1、使用@Document注解指明一个领域对象将被持久化到MongoDB中。