mongodb做为文档型数据库,是最像关系型数据库的。javascript
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <!-- 引入mongodb starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
# MongoDB spring.data.mongodb.uri=mongodb://localhost:27017/test #logging.level.com.example.demo=debug logging.level.org.springframework.data.mongodb.core.MongoTemplate=debug
import org.springframework.data.annotation.Id; //指明集合名 @Document(collection="user") public class User{ //指定id @Id private String id; private String password; private String name; private String gender; private Date createTime; //get/set } @Document(collection="order") public class Order { @Id private String id; private String shopName; //关联user集合 @DBRef private User user; //get/set } public class GroupResult { private Integer count; private String groupName; //get/set }
import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; /** * 发射能够说是java提供给程序员的做弊器了, * 利用反射能够建立并调用bean的私有方法, * 但这样就破坏了java的封装性,并且反射是 比较耗资源的 * 使用要谨慎 * @author 25395 * */ public class ReflectUtil { /** * 将实体中有值的属性放到map中 * @param object * @return */ public static Map<String,Object> entryToMap(Object object){ Map<String,Object> map=new HashMap<>(); try { Field[] fields = object.getClass().getDeclaredFields(); Object result=null; for(Field field: fields) { field.setAccessible(true); result = field.get(object); if(result!=null) { map.put(field.getName(), result); } } }catch (Exception e) { e.printStackTrace(); } return map; } }
import java.lang.reflect.Field; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.aggregation.GroupOperation; import org.springframework.data.mongodb.core.aggregation.MatchOperation; import org.springframework.data.mongodb.core.aggregation.ProjectionOperation; import org.springframework.data.mongodb.core.aggregation.UnwindOperation; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.util.StringUtils; import com.example.demo.bean.GroupResult; import com.example.demo.util.ReflectUtil; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.UpdateResult; public class MongodbServiceImpl { @Autowired private MongoTemplate mongoTemplate; /** * 带条件分组 * @param criteria * @param filed * @param collectionName * @return */ protected List<GroupResult> groupBy(Criteria criteria, String filed,String collectionName) { MatchOperation match = Aggregation.match(criteria); GroupOperation groupOperation = Aggregation.group(filed).count() .as("count"); ProjectionOperation project = Aggregation.project("count").and("_id") .as("groupName"); Aggregation agg = Aggregation.newAggregation(match,groupOperation,project); AggregationResults<GroupResult> results = mongoTemplate .aggregate(agg, collectionName, GroupResult.class); List<GroupResult> mappedResults = results.getMappedResults(); return mappedResults; } /** * 根据传入的字段,对集合进行分组 * @param filed:待分组的字段 * @param collectionName:集合名 * @return:[{_id=女, count=2, groupName=女}] */ protected List<GroupResult> groupBy(String filed,String collectionName) { GroupOperation groupOperation = Aggregation.group(filed).count() .as("count"); ProjectionOperation project = Aggregation.project("count").and("_id") .as("groupName"); Aggregation agg = Aggregation.newAggregation(groupOperation,project); AggregationResults<GroupResult> results = mongoTemplate .aggregate(agg, collectionName, GroupResult.class); List<GroupResult> mappedResults = results.getMappedResults(); return mappedResults; } /** * 内嵌集合分组查询 * @param filed 待分组字段,即要分组的字段 如:products.category * @param collectionName 集合名 * @return */ protected List<GroupResult> innerGroupBy(String filed,String collectionName) { String[] fileds = filed.split("\\."); UnwindOperation unwind = Aggregation.unwind(fileds[0]); GroupOperation groupOperation = Aggregation.group(filed).count() .as("count"); ProjectionOperation project = Aggregation.project("count").and("_id") .as("groupName"); Aggregation agg = Aggregation.newAggregation(unwind,groupOperation,project); AggregationResults<GroupResult> results = mongoTemplate .aggregate(agg, collectionName, GroupResult.class); List<GroupResult> mappedResults = results.getMappedResults(); return mappedResults; } /** * 根据传入实体,利用反射进行查询 * @param object * @param page * @return */ protected Page<?> findAll(Object object, Pageable page) { Criteria criatira=new Criteria(); try { Field[] fields = object.getClass().getDeclaredFields(); for(Field field : fields) { field.setAccessible(true); Object val = field.get(object); if(val != null) { String key = field.getName(); criatira.and(key).is(val); } } }catch (Exception e) { e.printStackTrace(); } return findAll(criatira, page,object.getClass()); } /** * 根据传入的查询条件,进行查询 * @param criatira * @param page * @param entityClass * @return */ protected <K> Page<K> findAll(Criteria criatira, Pageable page, Class<K> entityClass) { Query query = new Query(criatira); long totalCount = this.mongoTemplate.count(query, entityClass);//查询数量 Page<K> pages; List<K> list; if (totalCount > 0) { list = mongoTemplate.find(query.with(page), entityClass); pages = new PageImpl<>(list, page, totalCount); } else { pages = new PageImpl<>(Collections.emptyList()); } return pages; } /** * 查询全部知足条件的记录,不分页 * @param criatira * @param entityClass * @return */ protected <K> List<K> findAll(Criteria criatira, Class<K> entityClass) { Query query = new Query(criatira); List<K> list = mongoTemplate.find(query, entityClass); return list; } /** * 根据id进行有选择地更新,若是entry属性值为空,则将该值设置为空(当只有一列时,会删除该列) * @param id * @param map * @param entityClass */ protected long updateById(Object id, Map<String, Object> map, Class<?> entityClass) { Update update = new Update(); for (Map.Entry<String, Object> entry : map.entrySet()) { if (null == entry.getValue()) { update.unset(entry.getKey()); } else { update.set(entry.getKey(), entry.getValue()); } } UpdateResult updateMulti = mongoTemplate.updateMulti(new Query(Criteria.where("_id").is(id)), update, entityClass); return updateMulti.getModifiedCount(); } /** * 指定更新對象的id 的名,根據傳入對象有選擇地更新 * @param object :更新的對象 * @param idName : id名 */ protected long updateByEntry(Object object,String idName) { Map<String, Object> map = ReflectUtil.entryToMap(object); if(!StringUtils.hasText(idName)) { idName="id"; } Object idVal = map.get(idName); map.remove(idName); return updateById(idVal, map, object.getClass()); } /** * 根據傳入對象有選擇地更新(主键的key 默认为:id) * @param object :更新的對象 */ protected long updateByEntry(Object object) { return updateByEntry(object,null); } /** * 根据传入的ids 对指定集合进行删除 * @param ids * @param entityClass * @param idName * @return 删除的条数 */ protected long remove(List<Object> ids,Class<?> entityClass,String idName) { if(!StringUtils.hasText(idName)) { idName="id"; } Criteria criatira=Criteria.where(idName).in(ids); Query query = new Query(criatira); DeleteResult result = mongoTemplate.remove(query, entityClass); return result.getDeletedCount(); } /** * 根据传入的ids 对指定集合进行删除,注解默认为:id * @param ids * @param entityClass * @return 删除的条数 */ protected long remove(List<Object> ids,Class<?> entityClass) { return remove(ids, entityClass, null); } /** * 保存单个实体 * @param objectToSave */ protected void insert(Object objectToSave) { mongoTemplate.insert(objectToSave); } /** * 保存实体集合 * @param objectsToSave */ protected void insertAll(Collection<? extends Object> objectsToSave) { mongoTemplate.insertAll(objectsToSave); } }
import java.util.List; import java.util.Map; import org.springframework.data.domain.Page; import com.example.demo.bean.User; public interface UserService { void update(User user); Page<User> query(User user,Page<User> page) ; List<Map> groupBy(String filed,String collectionName); void remove(List<Object> ids); }
import java.util.Arrays; import java.util.List; import java.util.Map; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Order; import org.springframework.stereotype.Service; import com.example.demo.bean.User; import com.example.demo.service.UserService; @Service public class UserServiceImpl extends MongodbServiceImpl implements UserService{ @Override public void update(User user) { super.updateByEntry(user); } @Override public Page<User> query(User user,Page<User> page) { // Page<?> pages = super.findAll(user, PageRequest.of(0, 2,Sort.by(Direction.DESC,"createTime","gender"))); List<Order> orders=Arrays.asList(new Order(Direction.DESC,"createTime"),new Order(Direction.ASC,"gender")); Page<?> pages = super.findAll(user, PageRequest.of(0, 2,Sort.by(orders))); return (Page<User>) pages; } @Override public List<Map> groupBy(String filed,String collectionName){ return super.groupBy(filed, collectionName); } @Override public void remove(List<Object> ids) { super.remove(ids, User.class); } }
切记,html
①,mongodb不支持事务;java
---这个真没办法了呀,能想到的办件就是手动恢复了,将有更新的原始记录保存起来,若是发生异常就是将原来的数据设置回去。程序员
②,若是常对mongdb的一行的集合进行修改,切记用外键关联的方式,不然会形成锁表很严重web
更多注意事项,请参考:spring
https://www.cnblogs.com/l1pe1/p/7871859.htmlmongodb
一旦异常抛出,下面方法就不会执行,也没有回滚数据库
@Transactional @Override public void transact() { User user=new User(); user.setId("5b07fd0d75337d081c64c5e8"); user.setName("红米1"); super.updateByEntry(user); int i=9/0; System.out.println("===================="); user=new User(); user.setId("5b08bbef75337d0a58748083"); user.setName("刘亦菲"); super.updateByEntry(user); } @Transactional @Override public void repositoryTransact() { User user=new User(); user.setName("红米NOTE4X"); userRepsoitory.save(user); int i=9/0; System.out.println("===================="); user=new User(); user.setName("冬马"); userRepsoitory.save(user); }
db.employee.find().forEach( function(item){ db.employee.update({_id:item._id},{$set:{email:'ai@qq.com'}}) } )
BasicDBObject fieldsObject=new BasicDBObject(); fieldsObject.put("id","1"); String queryJson="{\"_id\":\"5b36f44be664da37b4fafe9f\"}"; String fieldJson="{\"_id\":\"1\",\"orderNo\":\"1\"}"; BasicQuery query = new BasicQuery(queryJson,fieldJson); query.addCriteria(Criteria.where("id").in(orderRecordMap.keySet())); List<B2bOrder> orderList = mongoTemplate.find(query, B2bOrder.class);
①,SpringBoot 没有提供 mongoxxxCustomizer,但springdata提供了一个AbstractMongoConfigurationapp
import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.config.AbstractMongoConfiguration; import com.mongodb.MongoClient; @Configuration public class MongoConfig extends AbstractMongoConfiguration{ @Override public MongoClient mongoClient() { return new MongoClient("127.0.0.1",27017); } @Override protected String getDatabaseName() { return "test"; } }