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"; } }