Spring整合MongoDB增删改查及批量新增修改
Posted Lossdate
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring整合MongoDB增删改查及批量新增修改相关的知识,希望对你有一定的参考价值。
简单封装了下基础的增删改查以及批量操作,方便后续的拓展
一、配置
-
applicationContext.xml
#beans添加 xmlns:mongo="http://www.springframework.org/schema/data/mongo" http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.5.xsd #配置 <mongo:mongo id="mongo" replica-set="${mongo.hostPort}"> <!-- 一些连接属性的设置 --> <mongo:options connections-per-host="${mongo.connectionsPerHost}" threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}" connect-timeout="${mongo.connectTimeout}" max-wait-time="${mongo.maxWaitTime}" auto-connect-retry="${mongo.autoConnectRetry}" socket-keep-alive="${mongo.socketKeepAlive}" socket-timeout="${mongo.socketTimeout}" slave-ok="${mongo.slaveOk}" write-number="1" write-timeout="0" write-fsync="true" /> </mongo:mongo> <mongo:db-factory dbname="database" mongo-ref="mongo" /> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongo" ref="mongo" /> <constructor-arg name="databaseName" value="test" /> </bean>
mongo.hostPort=127.0.0.1:27017 mongo.connectionsPerHost=8 mongo.threadsAllowedToBlockForConnectionMultiplier=4 #连接超时时间 mongo.connectTimeout=1000 #等待时间 mongo.maxWaitTime=1500 mongo.autoConnectRetry=true mongo.socketKeepAlive=true #Socket超时时间 mongo.socketTimeout=1500 mongo.slaveOk=true
二、代码整合
-
接口
/* * BaseEntity 为基础实体类,参数随意 */ public interface BaseMongoInterface<T extends BaseEntity> { /** * 按 id 查询 * @param clazz Class * @param id 查询的id * @param collectionName collectionName * @return Entity */ T get(final Class<T> clazz, final String id, final String collectionName); /** * insert * @param entity new Entity * @param collectionName collectionName * @return 1 */ int insert(final T entity, final String collectionName); /** * update * @param clazz Class * @param id update 的 id * @param needUpdateParams 需要更新的字段和值 * @param collectionName collectionName * @return count */ int update(final Class<T> clazz, String id, Map<String, Object> needUpdateParams, final String collectionName); /** * find * @param clazz Class * @param whereParams 查询条件 * @param sortParam 排序字段 * @param sortWay 排序方式("ASC", "DESC") * @param collectionName collectionName * @return List<Entity> */ List<T> find(final Class<T> clazz, Map<String, Object> whereParams, String sortParam, String sortWay, final String collectionName); /** * find one * @param clazz Class * @param whereParams 查询条件 * @param sortParam 排序字段 * @param sortWay 排序方式("ASC", "DESC") * @param collectionName collectionName * @return Entity */ T findOne(final Class<T> clazz, Map<String, Object> whereParams, String sortParam, String sortWay, final String collectionName); /** * 根据实体 批量 insert * @param list 批量插入的实体 list * @param collectionName collectionName * @return count */ int insertBatch(final List<T> list, final String collectionName); /** * 根据查询条件 批量 update * @param clazz Class * @param whereParams 查询条件 * @param needUpdateParams 需要更新的字段 * @param collectionName collectionName * @return count */ int updateBatch(final Class<T> clazz, Map<String, Object> whereParams, Map<String, Object> needUpdateParams, final String collectionName); /** * 根据实体 批量 update * @param list 需要 update 的实体 list * @param collectionName collectionName * @param upsert 实体 id 不存在的情况是否需要插入 * @param needNullParam 是否更新实体内为null的字段 * @return count */ int updateBatch(final List<T> list, final String collectionName, boolean upsert, boolean needNullParam); /** * 分页查询 * @param clazz Class * @param whereParams 查询条件 * @param sortParam 排序字段 * @param sortWay 排序方式("ASC", "DESC") * @param collectionName collectionName * @param limitStart 起始 * @param pageSize 查询多少条 * @return List<Entity> */ List<T> page(final Class<T> clazz, Map<String, Object> whereParams, String sortParam, String sortWay, final String collectionName, int limitStart, int pageSize); /** * 查询数量 * @param clazz Class * @param whereParams 查询条件 * @param collectionName collectionName * @return count */ long count(final Class<T> clazz, Map<String, Object> whereParams, final String collectionName); /** * 删除 * @param clazz Class * @param whereParams 查询条件 * @param collectionName collectionName * @return count */ int remove(final Class<T> clazz, Map<String, Object> whereParams, final String collectionName); }
-
批量更新工具类
public class BathUpdateOptions { private Query query; private Update update; private boolean upsert = false; private boolean multi = false; public BathUpdateOptions() { } public BathUpdateOptions(Query query, Update update, boolean upsert, boolean multi) { this.query = query; this.update = update; this.upsert = upsert; this.multi = multi; } //getter and setter ... }
public class BatchUpdateHelper { public static <T> Map<String, Object> beanToMap(T bean, boolean needNullParam) { Map<String, Object> map = Maps.newHashMap(); if (bean != null) { BeanMap beanMap = BeanMap.create(bean); for (Object key : beanMap.keySet()) { if(!needNullParam && beanMap.get(key) == null) { continue; } map.put(key + "", beanMap.get(key)); } } return map; } public static int bathUpdate(MongoTemplate mongoTemplate, List<BathUpdateOptions> options, String collectionName) { return doBathUpdate(mongoTemplate.getCollection(collectionName), collectionName, options, true); } private static int doBathUpdate(DBCollection dbCollection, String collName, List<BathUpdateOptions> options, boolean ordered) { DBObject command = new BasicDBObject(); command.put("update", collName); List<BasicDBObject> updateList = new ArrayList<>(); for (BathUpdateOptions option : options) { BasicDBObject update = new BasicDBObject(); update.put("q", option.getQuery().getQueryObject()); update.put("u", option.getUpdate().getUpdateObject()); update.put("upsert", option.isUpsert()); update.put("multi", option.isMulti()); updateList.add(update); } command.put("updates", updateList); command.put("ordered", ordered); CommandResult commandResult = dbCollection.getDB().command(command); return Integer.parseInt(commandResult.get("n").toString()); } }
-
功能实现
@Component public abstract class BaseMongoInterfaceImpl<T extends BaseEntity> implements BaseMongoInterface<T> { @Autowired private MongoTemplate mongoTemplate; @Override public T get(@NotNull Class<T> clazz, @NotNull String id, @NotNull String collectionName) { return mongoTemplate.findById(id, clazz, collectionName); } @Override public int insert(@NotNull T entity, @NotNull String collectionName) { mongoTemplate.insert(entity, collectionName); return 1; } @Override public int update(@NotNull Class<T> clazz, @NotNull String id, @NotNull Map<String, Object> needUpdateParams, @NotNull String collectionName) { Query query = new Query(); query.addCriteria(Criteria.where("_id").is(id)); Update update = new Update(); needUpdateParams.forEach(update::set); WriteResult writeResult = mongoTemplate.updateFirst(query, update, clazz, collectionName); return writeResult.getN(); } @Override public List<T> find(@NotNull Class<T> clazz, Map<String, Object> whereParams, String sortParam, String sortWay, @NotNull String collectionName) { Query query = getFindQuery(whereParams, sortParam, sortWay); return mongoTemplate.find(query, clazz, collectionName); } private Query getFindQuery(Map<String, Object> whereParams, String sortParam, String sortWay) { Query query = new Query(); if (whereParams != null && whereParams.size() > 0) { AtomicReference<Criteria> criteria = new AtomicReference<>(); AtomicInteger index = new AtomicInteger(); whereParams.forEach((k,v) -> { if(k.equals("id")) { k = "_id"; } if(index.get() == 0) { criteria.set(Criteria.where(k).is(v)); } else { criteria.get().and(k).is(v); } index.getAndIncrement(); }); query.addCriteria(criteria.get()); } if(StringUtils.isNotBlank(sortParam)) { if(sortWay == null) {sortWay = "ASC";} if("ASC".equals(sortWay)) { query.with(new Sort(new Sort.Order(Sort.Direction.ASC, sortParam))); } else { query.with(new Sort(new Sort.Order(Sort.Direction.DESC, sortParam))); } } return query; } @Override public T findOne(@NotNull Class<T> clazz, @NotNull Map<String, Object> whereParams, String sortParam, String sortWay, @NotNull String collectionName) { Query query = getFindQuery(whereParams, sortParam, sortWay); query.skip(0); query.limit(1); List<T> dataList = mongoTemplate.find(query, clazz, collectionName); return dataList.isEmpty() ? null : dataList.get(0); } /** * 批量操作批次最大数 */ public static final Integer BATCH_CEILING = 300; @Override public int insertBatch(@NotNull List<T> list, @NotNull String collectionName) { List<List<T>> batchList = new ArrayList<>(); int len = BATCH_CEILING; if(!list.isEmpty()) { if(list.size() > len) { //优化insertBatch,切割处理 int size = list.size(); int count = (size + len - 1) / len; for (int i = 0; i < count; i++) { List<T> subList = list.subList(i * len, (Math.min((i + 1) * len, size))); batchList.add(subList); } if(batchList.size() > 0) { for (List<T> subList : batchList) { mongoTemplate.insert(subList, collectionName); } } } else { mongoTemplate.insert(list, collectionName); } } return list.size(); } @Override public int updateBatch(@NotNull Class<T> clazz, @NotNull Map<String, Object> whereParams, @NotNull Map<String, Object> needUpdateParams, @NotNull String collectionName) { Query query = new Query(); AtomicReference<Criteria> criteria = new AtomicReference<>(); AtomicInteger index = new AtomicInteger(); whereParams.forEach((k,v) -> { if(index.get() == 0) { criteria.set(Criteria.where(k).is(v)); } else { criteria.get().and(k).is(v); } index.getAndIncrement(); }); query.addCriteria(criteria.get()); Update update = new Update(); needUpdateParams.forEach(update::set); WriteResult writeResult = mongoTemplate.updateMulti(query, update, clazz, collectionName); return writeResult.getN(); } @Override public int updateBatch(@NotNull List<T> list, @NotNull String collectionName, @NotNull boolean upsert, @NotNull boolean needNullParam) { int result = 0; List<BathUpdateOptions> optionsList = new ArrayList<>(); Map<String, Object> needUpdateParams; for (T entity : list) { if(StringUtils.isBlank(entity.getId())) { continue; } Query query = new Query(); query.addCriteria(Criteria.where("_id").is(entity.getId())); entity.setId(null); needUpdateParams = BatchUpdateHelper.beanToMap(entity, needNullParam); Update update = new Update(); needUpdateParams.forEach(update::set); optionsList.add(new BathUpdateOptions(query, update, upsert, true)); } List<List<BathUpdateOptions>> batchList = new ArrayList<>(); int len = BATCH_CEILING; if(!optionsList.isEmpty()) { if(optionsList.size() > len) { //优化insertBatch,切割处理 int size = optionsList.size(); int count = (size + len - 1) / len; for (int i = 0; i < count; i++) { List<BathUpdateOptions> subList = optionsList.subList(i * len, (Math.min((i + 1) * len, size))); batchList.add(subList); } if(batchList.size() > 0) { for (List<BathUpdateOptions> subList : batchList) { result += BatchUpdateHelper.bathUpdate(mongoTemplate, subList, collectionName); } } } else { result = BatchUpdateHelper.bathUpdate(mongoTemplate, optionsList, collectionName); } } return result; } @Override public List<T> page(@NotNull Class<T> clazz, Map<String, Object> whereParams, String sortParam, String sortWay, @NotNull final String collectionName, @NotNull int limitStart, @NotNull int pageSize) { Query query = getFindQuery(whereParams, sortParam, sortWay); query.skip(limitStart); query.limit(pageSize); return mongoTemplate.find(query, clazz, collectionName); } @Override public long count(@NotNull Class<T> clazz, @NotNull Map<String, Object> whereParams, @NotNull final String collectionName) { Query query = getFindQuery(whereParams, null, null); return mongoTemplate.count(query, clazz, collectionName); } @Override public int remove(@NotNull Class<T> clazz, @NotNull Map<String, Object> whereParams, @NotNull final String collectionName) { Query query = getFindQuery(whereParams, null, null); WriteResult remove = mongoTemplate.remove(query, clazz, collectionName); return remove.getN(); } }
以上是关于Spring整合MongoDB增删改查及批量新增修改的主要内容,如果未能解决你的问题,请参考以下文章
04-springboot整合elasticsearch初识-简单增删改查及复杂排序,分页,聚合操作