Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 弹簧数据:默认值';未删除';使用软删除策略时基于方法的自动查询逻辑_Java_Spring Data Jpa_Spring Data_Spring Data Mongodb - Fatal编程技术网

Java 弹簧数据:默认值';未删除';使用软删除策略时基于方法的自动查询逻辑

Java 弹簧数据:默认值';未删除';使用软删除策略时基于方法的自动查询逻辑,java,spring-data-jpa,spring-data,spring-data-mongodb,Java,Spring Data Jpa,Spring Data,Spring Data Mongodb,假设我们使用软删除策略:不从存储中删除任何内容;相反,记录/文档/任何内容的“deleted”属性/列设置为true以使其“deleted”。稍后,查询方法只应返回未删除的条目 让我们以MongoDB为例(alghough JPA也很有趣) 对于由MongoRepository定义的标准方法,我们可以扩展默认实现(simplemonogrepository),覆盖感兴趣的方法并使它们忽略“已删除”文档 但是,当然,我们也希望使用自定义查询方法,如 List<Person> findB

假设我们使用软删除策略:不从存储中删除任何内容;相反,记录/文档/任何内容的“deleted”属性/列设置为true以使其“deleted”。稍后,查询方法只应返回未删除的条目

让我们以MongoDB为例(alghough JPA也很有趣)

对于由
MongoRepository
定义的标准方法,我们可以扩展默认实现(
simplemonogrepository
),覆盖感兴趣的方法并使它们忽略“已删除”文档

但是,当然,我们也希望使用自定义查询方法,如

List<Person> findByFirstName(String firstName)
列出findByFirstName(字符串名)
在软删除环境中,我们被迫执行以下操作

List<person> findByFirstNameAndDeletedIsFalse(String firstName)
列出FindByFirstName和DeleteDisFalse(字符串名)
或者使用
@Query
手动编写查询(始终添加关于“未删除”的相同样板条件)

问题来了:是否可以将此“未删除”条件自动添加到任何生成的查询中?我在文档中没有找到任何东西

我在看Spring数据(Mongo和JPA)2.1.6

类似问题
  • 这里他们建议使用Hibernate的
    @Where
    注释,该注释仅适用于JPA+Hibernate,如果在某些查询中仍然需要访问已删除的项目,则不清楚如何覆盖它
  • 在这里,人们要么建议使用相同的基于
    @的方法,要么解决方案的适用性受限于已经定义的标准方法,而不是自定义方法

  • 事实证明,对于Mongo(至少对于spring data Mongo 2.1.6),我们可以侵入标准的
    QueryLookupStrategy
    实现,添加所需的“软删除文档不被查找者的行为看到”:

    public class SoftDeleteMongoQueryLookupStrategy implements QueryLookupStrategy {
        private final QueryLookupStrategy strategy;
        private final MongoOperations mongoOperations;
    
        public SoftDeleteMongoQueryLookupStrategy(QueryLookupStrategy strategy,
                MongoOperations mongoOperations) {
            this.strategy = strategy;
            this.mongoOperations = mongoOperations;
        }
    
        @Override
        public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
                NamedQueries namedQueries) {
            RepositoryQuery repositoryQuery = strategy.resolveQuery(method, metadata, factory, namedQueries);
    
            // revert to the standard behavior if requested
            if (method.getAnnotation(SeesSoftlyDeletedRecords.class) != null) {
                return repositoryQuery;
            }
    
            if (!(repositoryQuery instanceof PartTreeMongoQuery)) {
                return repositoryQuery;
            }
            PartTreeMongoQuery partTreeQuery = (PartTreeMongoQuery) repositoryQuery;
    
            return new SoftDeletePartTreeMongoQuery(partTreeQuery);
        }
    
        private Criteria notDeleted() {
            return new Criteria().orOperator(
                    where("deleted").exists(false),
                    where("deleted").is(false)
            );
        }
    
        private class SoftDeletePartTreeMongoQuery extends PartTreeMongoQuery {
            SoftDeletePartTreeMongoQuery(PartTreeMongoQuery partTreeQuery) {
                super(partTreeQuery.getQueryMethod(), mongoOperations);
            }
    
            @Override
            protected Query createQuery(ConvertingParameterAccessor accessor) {
                Query query = super.createQuery(accessor);
                return withNotDeleted(query);
            }
    
            @Override
            protected Query createCountQuery(ConvertingParameterAccessor accessor) {
                Query query = super.createCountQuery(accessor);
                return withNotDeleted(query);
            }
    
            private Query withNotDeleted(Query query) {
                return query.addCriteria(notDeleted());
            }
        }
    }
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface SeesSoftlyDeletedRecords {
    }
    
    除非
    @SeesSoftlyDeletedRecords
    要求避免,否则我们只需在所有查询中添加'and not deleted'条件

    然后,我们需要以下基础结构来插入我们的
    querylikupstrategy
    实现:

    public class SoftDeleteMongoRepositoryFactory extends MongoRepositoryFactory {
        private final MongoOperations mongoOperations;
    
        public SoftDeleteMongoRepositoryFactory(MongoOperations mongoOperations) {
            super(mongoOperations);
            this.mongoOperations = mongoOperations;
        }
    
        @Override
        protected Optional<QueryLookupStrategy> getQueryLookupStrategy(QueryLookupStrategy.Key key,
                QueryMethodEvaluationContextProvider evaluationContextProvider) {
            Optional<QueryLookupStrategy> optStrategy = super.getQueryLookupStrategy(key,
                    evaluationContextProvider);
            return optStrategy.map(this::createSoftDeleteQueryLookupStrategy);
        }
    
        private SoftDeleteMongoQueryLookupStrategy createSoftDeleteQueryLookupStrategy(QueryLookupStrategy strategy) {
            return new SoftDeleteMongoQueryLookupStrategy(strategy, mongoOperations);
        }
    }
    
    public class SoftDeleteMongoRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
            extends MongoRepositoryFactoryBean<T, S, ID> {
    
        public SoftDeleteMongoRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
            super(repositoryInterface);
        }
    
        @Override
        protected RepositoryFactorySupport getFactoryInstance(MongoOperations operations) {
            return new SoftDeleteMongoRepositoryFactory(operations);
        }
    }
    
    如果需要动态确定特定存储库是需要“软删除”还是需要常规“硬删除”存储库,我们可以反省存储库接口(或域类),并决定是否需要更改
    QueryLookupStrategy

    对于JPA,如果不在
    PartTreeJpaQuery
    中重写(可能重复)大部分代码,这种方法就无法工作

    @EnableMongoRepositories(repositoryFactoryBeanClass = SoftDeleteMongoRepositoryFactoryBean.class)