赞
踩
MongoDB 默认的删除方式是物理删除,但很多时候我们的需求都是逻辑删除,即通过某个字段去判断是否删除,类似于 MyBatisPlus 的 @TableLogic 注解
逻辑删除注解 @SoftDelete
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SoftDelete {
}
公共字段实体 BaseDO,所有实体都将继承它
@Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) public class BaseDO implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "主键") @Mapping("id") @Id private Long id; @SoftDelete @ApiModelProperty(value = "逻辑删除标记") private String deleteFlag; }
@Configuration public class MongoCommonFieldsEventListener extends AbstractMongoEventListener { @Autowired ICurrentUserProvider currentUserProvider; @Override public void onBeforeConvert(BeforeConvertEvent event) { Object source = event.getSource(); if (source instanceof BaseDO) { BaseDO entity = BaseDO.class.cast(source); if (entity.getCreationDate() == null) { entity.setDeleteFlag("N"); } } } }
默认的删除方法 deleteById,会物理删除数据
重写:更新 deleteFlag 字段为 Y
public void delete(Long id) {
TestPO po = new TestPO();
po.setId(id);
po.setDeleteFlag("Y");
mongoTemplate.save(testPO);
}
过滤传参
自定义查询器
public class CusPartTreeMongoQuery extends PartTreeMongoQuery { public CusPartTreeMongoQuery(MongoQueryMethod method, MongoOperations mongoOperations, SpelExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { super(method, mongoOperations, expressionParser, evaluationContextProvider); } @Override protected Query createQuery(ConvertingParameterAccessor accessor) { Query query = super.createQuery(accessor); query.fields(); MongoQueryMethod queryMethod = super.getQueryMethod(); MongoEntityMetadata<?> entityInformation = queryMethod.getEntityInformation(); Class<?> javaType = entityInformation.getJavaType(); Optional<Field> annotationFieldOne = ReflectionUtil.getAnnotationFieldOne(javaType, SoftDelete.class); annotationFieldOne.ifPresent(field -> { try { query.addCriteria(Criteria.where(field.getName()).is("N")); } catch (Exception ignored) { } }); return query; } }
ReflectionUtil 反射工具类:根据注解获取字段名
public class ReflectionUtil { private ReflectionUtil(){} public static Collection<Field> getAnnotationField(Object object, Class<? extends Annotation> annotation){ return getAnnotationField(object.getClass(),annotation); } public static Collection<Field> getAnnotationField(Class<?> clazz,Class<? extends Annotation> annotation){ List<Field> result = new ArrayList<>(); Collection<Field> allDeclaredFields = getDeclaredFields(clazz); for (Field declaredField : allDeclaredFields) { if (declaredField.isAnnotationPresent(annotation)){ result.add(declaredField); } } return result; } public static Optional<Field> getAnnotationFieldOne(Class<?> clazz, Class<? extends Annotation> annotation){ Collection<Field> result = getAnnotationField(clazz, annotation); return result.stream().findFirst(); } public static Optional<Field> getFieldsByFieldName(Class<?> sourceClass,String fieldName){ Collection<Field> declaredFields = getDeclaredFields(sourceClass); return declaredFields.stream().filter(field -> field.getName().equals(fieldName)).findFirst(); } public static Collection<Field> getDeclaredFields(Class<?> sourceClass) { ArrayList<Field> result = new ArrayList<>(); while (sourceClass.getDeclaredFields().length != 0) { result.addAll(Arrays.asList(sourceClass.getDeclaredFields().clone())); sourceClass = sourceClass.getSuperclass(); } return result; } }
工厂类
CusMongoRepositoryFactory
自定义工厂类,因为默认工厂类不会加载自定义的查询器
重点是最后一行,创建自定义查询器:return new CusPartTreeMongoQuery
public class CusMongoRepositoryFactory extends MongoRepositoryFactory { private static final SpelExpressionParser EXPRESSION_PARSER = new SpelExpressionParser(); private final MongoOperations operations; private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext; /** * Creates a new {@link MongoRepositoryFactory} with the given {@link MongoOperations}. * * @param mongoOperations must not be {@literal null}. */ public CusMongoRepositoryFactory(MongoOperations mongoOperations) { super(mongoOperations); Assert.notNull(mongoOperations, "MongoOperations must not be null!"); this.operations = mongoOperations; this.mappingContext = mongoOperations.getConverter().getMappingContext(); } @Override protected Optional<QueryLookupStrategy> getQueryLookupStrategy(QueryLookupStrategy.Key key, QueryMethodEvaluationContextProvider evaluationContextProvider) { return Optional.of(new CusMongoRepositoryFactory.MongoQueryLookupStrategy(operations, evaluationContextProvider, mappingContext)); } /** * {@link QueryLookupStrategy} to create instances. * * @author Oliver Gierke * @author Thomas Darimont */ private static class MongoQueryLookupStrategy implements QueryLookupStrategy { private final MongoOperations operations; private final QueryMethodEvaluationContextProvider evaluationContextProvider; MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext; public MongoQueryLookupStrategy(MongoOperations operations, QueryMethodEvaluationContextProvider evaluationContextProvider, MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) { this.operations = operations; this.evaluationContextProvider = evaluationContextProvider; this.mappingContext = mappingContext; } /* * (non-Javadoc) * @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.projection.ProjectionFactory, org.springframework.data.repository.core.NamedQueries) */ @Override public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory, NamedQueries namedQueries) { MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, mappingContext); String namedQueryName = queryMethod.getNamedQueryName(); if (namedQueries.hasQuery(namedQueryName)) { String namedQuery = namedQueries.getQuery(namedQueryName); return new StringBasedMongoQuery(namedQuery, queryMethod, operations, EXPRESSION_PARSER, evaluationContextProvider); } else if (queryMethod.hasAnnotatedAggregation()) { return new StringBasedAggregation(queryMethod, operations, EXPRESSION_PARSER, evaluationContextProvider); } else if (queryMethod.hasAnnotatedQuery()) { return new StringBasedMongoQuery(queryMethod, operations, EXPRESSION_PARSER, evaluationContextProvider); } else { return new CusPartTreeMongoQuery(queryMethod, operations, EXPRESSION_PARSER, evaluationContextProvider); } } } }
CusMongoRepositoryFactoryBean
public class CusMongoRepositoryFactoryBean <T extends Repository<S, ID>, S, ID extends Serializable> extends MongoRepositoryFactoryBean<T, S, ID> {
public CusMongoRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
super(repositoryInterface);
}
@Override
protected RepositoryFactorySupport getFactoryInstance(MongoOperations operations) {
return new CusMongoRepositoryFactory(operations);
}
}
在启动类加载装配
@SpringBootApplication
@EnableMongoRepositories(repositoryFactoryBeanClass = CusMongoRepositoryFactoryBean.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application .class, args);
}
}
接口继承 PagingAndSortingRepository 和 QueryByExampleExecutor
@NoRepositoryBean
public interface CusMongoRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
...
}
实现类 CusMongoRepositoryImpl
查询方法添加查询条件,以 findAll 做例子
public class CusMongoRepositoryImpl<T, ID> implements CusMongoRepository<T, ID> { private static final String SOFT_DELETION_KEY = "deleteFlag"; private static final Object DELETE_TRUE = "Y"; private static final Object DELETE_FALSE = "N"; private final MongoOperations mongoOperations; private final MongoEntityInformation<T, ID> entityInformation; public CusMongoRepositoryImpl( MongoEntityInformation<T, ID> metadata, MongoOperations mongoOperations) { Assert.notNull(metadata, "MongoEntityInformation must not be null!"); Assert.notNull(mongoOperations, "MongoOperations must not be null!"); this.entityInformation = metadata; this.mongoOperations = mongoOperations; } @Override public List<T> findAll(@Nullable Query query) { if (query == null) { return Collections.emptyList(); } query.addCriteria(where(SOFT_DELETION_KEY).is(DELETE_FALSE)); return mongoOperations.find( query, entityInformation.getJavaType(), entityInformation.getCollectionName()); } }
在启动类加载装配
@SpringBootApplication
@EnableMongoRepositories(repositoryFactoryBeanClass = CusMongoRepositoryFactoryBean.class,repositoryBaseClass = CusMongoRepositoryImpl.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application .class, args);
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。