Mongodb的一些基本操作

MongoDB配置,CRUD操作,条件查询

简单记录一下自己使用的MongoDB的一些操作。

配置

处理了_class的不必要的生成,自定义一个递增的注解:

//mongodb中生成的记录忽略_class字段
@Configuration
public class MongoConfig {
	@Bean
	public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context,
			BeanFactory beanFactory) {
		DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
		MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
		try {
			mappingConverter.setCustomConversions(beanFactory.getBean(CustomConversions.class));
		} catch (NoSuchBeanDefinitionException ignore) {
		}
		// Don't save _class to mongo
		mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
		return mappingConverter;
	}
}

自定义递增注解,mongodb无法设置字段自动递增,mongodb数据类型是一些基本数据类型,如果字段不设置int,long类型无法实现自动注解的功能。通过监听mongodb的生命周期事件,然后进行重写实现。

@Component
public class MongoDBEventListener extends AbstractMongoEventListener<Object> {
	
	@SuppressWarnings("unused")
	private static final Logger LOG = LoggerFactory.getLogger(MongoDBEventListener.class);
	
	@Autowired
	private MongoTemplate mongoTemplate;
 
	/**
	 * 在新增记录的时候,回调接口方法,监听文档插入记录的操作,使用反射方法对ID进行自增
	 * 
	 * @param event
	 * @since 1.8
	 */
	@Override
	public void onBeforeConvert(BeforeConvertEvent<Object> event) {
		final Object source = event.getSource(); // 获取事件最初发生的对象
		if (source != null) {
			// 使用反射工具类,实现回调接口的方法,对成员进行操作
			ReflectionUtils.doWithFields(source.getClass(), new FieldCallback() {
				
				@Override
				public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
					ReflectionUtils.makeAccessible(field); // 使操作的成员可访问
					// 如果是带有@AutoIncrement注解的,成员调用getter方法返回的类型是Number类型的,返回的类型都是0的(没有赋值,默认为0)
					if (field.isAnnotationPresent(AutoIncrement.class) && field.get(source) instanceof Number
							&& field.getLong(source) == 0) {
						String collName = source.getClass().getSimpleName().substring(0, 1).toLowerCase()
								+ source.getClass().getSimpleName().substring(1);
						// setter方法的调用,使ID成员属性,进行自增
						field.set(source, getNextId(collName));
					}
				}
			});
		}
	}
	
	/**
	 * 返回下一个自增的ID
	 * 
	 * @param collName
	 *            集合名称(一般规则是,类名的第一个字母小写,然后按照驼峰书写法)
	 * @return Long 序列值
	 */
	private Long getNextId(String collName) {
		Query query = new Query(Criteria.where("collName").is(collName));
		List<SequenceId> list = mongoTemplate.find(query, SequenceId.class);
		SequenceId seq = null;
		Date now = new Date();
		if(list.size() > 0){
			Update update = new Update();
			update.inc("seqId", 1).set("gmtUpdate",now);
			FindAndModifyOptions options = new FindAndModifyOptions();
			options.upsert(true);
			options.returnNew(true);
			seq = mongoTemplate.findAndModify(query, update, options, SequenceId.class);
			return seq.getSeqId();
		}else{
			seq = new SequenceId();
			seq.setCollName(collName);
			seq.setGmtCreate(now);
			seq.setIsDelete("0");
			seq.setSeqId((long) 1);
			mongoTemplate.save(seq);
			return seq.getSeqId();
		}
	}
	
	/**
	 * Captures {@link BeforeSaveEvent}.
	 * 
	 * @param event will never be {@literal null}.
	 * @since 1.8
	 */
	@Override
	public void onBeforeSave(BeforeSaveEvent<Object> event) {
		//super.onBeforeSave(event);
	}

	/**
	 * Captures {@link AfterSaveEvent}.
	 * 
	 * @param event will never be {@literal null}.
	 * @since 1.8
	 */
	@Override
	public void onAfterSave(AfterSaveEvent<Object> event) {
		//super.onAfterSave(event);
	}

	/**
	 * 过滤掉isDelete=1 的数据
	 * 
	 */
	@Override
	public void onAfterLoad(AfterLoadEvent<Object> event) {
		//super.onAfterLoad(event);
	}

	/**
	 * Captures {@link AfterConvertEvent}.
	 * 
	 * @param event will never be {@literal null}.
	 * @since 1.8
	 */
	@Override
	public void onAfterConvert(AfterConvertEvent<Object> event) {
		//super.onAfterConvert(event);
	}

	/**
	 * Captures {@link AfterDeleteEvent}.
	 * 
	 * @param event will never be {@literal null}.
	 * @since 1.8
	 */
	@Override
	public void onAfterDelete(AfterDeleteEvent<Object> event) {
		//super.onAfterDelete(event);
	}

	/**
	 * Capture {@link BeforeDeleteEvent}.
	 * 
	 * @param event will never be {@literal null}.
	 * @since 1.8
	 */
	@Override
	public void onBeforeDelete(BeforeDeleteEvent<Object> event) {
		//super.onBeforeDelete(event);
	}


}

CRUD操作

简单的CRUD操作可以继承MongoRepository。也可以注入MongoTemplate 或者是MongoOperations进行一些操作,这两个类里面封装了很多原生的方法。

条件查询

  • 继承MongoRepository
   @Override
	<S extends T> List<S> findAll(Example<S> example);

	/* 
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example, org.springframework.data.domain.Sort)
	 */
	@Override
	<S extends T> List<S> findAll(Example<S> example, Sort sort);

Example 的使用利用一个对象设置字段值,

/*
 * Copyright 2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.data.domain;

import org.springframework.util.ClassUtils;

/**
 * Support for query by example (QBE). An {@link Example} takes a {@code probe} to define the example. Matching options
 * and type safety can be tuned using {@link ExampleMatcher}.
 *
 * @author Christoph Strobl
 * @author Mark Paluch
 * @author Oliver Gierke
 * @param <T> the type of the probe.
 * @since 1.12
 */
public interface Example<T> {

	/**
	 * Create a new {@link Example} including all non-null properties by default.
	 *
	 * @param probe must not be {@literal null}.
	 * @return
	 */
	static <T> Example<T> of(T probe) {
		return new TypedExample<>(probe, ExampleMatcher.matching());
	}

	/**
	 * Create a new {@link Example} using the given {@link ExampleMatcher}.
	 *
	 * @param probe must not be {@literal null}.
	 * @param matcher must not be {@literal null}.
	 * @return
	 */
	static <T> Example<T> of(T probe, ExampleMatcher matcher) {
		return new TypedExample<>(probe, matcher);
	}

	/**
	 * Get the example used.
	 *
	 * @return never {@literal null}.
	 */
	T getProbe();

	/**
	 * Get the {@link ExampleMatcher} used.
	 *
	 * @return never {@literal null}.
	 */
	ExampleMatcher getMatcher();

	/**
	 * Get the actual type for the probe used. This is usually the given class, but the original class in case of a
	 * CGLIB-generated subclass.
	 *
	 * @return
	 * @see ClassUtils#getUserClass(Class)
	 */
	@SuppressWarnings("unchecked")
	default Class<T> getProbeType() {
		return (Class<T>) ClassUtils.getUserClass(getProbe().getClass());
	}
}

利用ExampleMatcher matcher可以设置一些条件

可以参考
https://blog.csdn.net/moshowgame/article/details/80282813

  • 另外的一种条件拼接采用MongoTemplate 的方法
    @Override
	public List<RecordApi> findByPage(RecordApiForm form, Pageable pageable) {
		Query query = new Query();
		if (StringUtils.isNotBlank(form.getChannel())) {
			query.addCriteria(Criteria.where("channel").regex("^.*" + form.getChannel() + ".*$"));
		}
		if (StringUtils.isNotBlank(form.getBusiness())) {
			query.addCriteria(Criteria.where("business").regex("^.*" + form.getBusiness() + ".*$"));
		}
		if (StringUtils.isNotBlank(form.getMethod())) {
			query.addCriteria(Criteria.where("method").regex("^.*" + form.getMethod() + ".*$"));
		}
		if (isEmpty(form.getStart_time()) && isEmpty(form.getEnd_time())) {
			query.addCriteria(Criteria.where("gmtCreate").gte(form.getStart_time()).lte(form.getEnd_time()));
		} else if (isEmpty(form.getStart_time())) {
			query.addCriteria(Criteria.where("gmtCreate").gte(form.getStart_time()));
		} else if (isEmpty(form.getEnd_time())) {
			query.addCriteria(Criteria.where("gmtCreate").lte(form.getEnd_time()));
		}
		if (isEmpty(pageable)) {
			query.with(pageable);
		}
		return mongoTemplate.find(query, RecordApi.class);
	}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值