无法覆盖可分页的Spring数据-Spring Neo4j

时间:2018-08-15 08:21:46

标签: java spring-boot spring-data-jpa spring-data spring-data-neo4j

我需要覆盖spring数据提供的Pageable类,然后覆盖findAll提供的SimpleNeo4jRepository方法。

但是这样做,服务器启动时出现错误 Caused by: java.lang.IllegalArgumentException: Paging query needs to have a Pageable parameter! Offending method public abstract com.app.backend.repository.pagination.AppPage com.app.backend.repository.BaseRepository.findAll(com.app.backend.repository.pagination.AppPageRequest) at org.springframework.util.Assert.isTrue(Assert.java:116) ~[spring-core-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.data.repository.query.QueryMethod.<init>(QueryMethod.java:99) ~[spring-data-commons-2.0.9.RELEASE.jar:2.0.9.RELEASE] at org.springframework.data.neo4j.repository.query.GraphQueryMethod.<init>(GraphQueryMethod.java:41) ~[spring-data-neo4j-5.0.9.RELEASE.jar:5.0.9.RELEASE] at org.springframework.data.neo4j.repository.query.GraphQueryLookupStrategy.resolveQuery(GraphQueryLookupStrategy.java:49) ~[spring-data-neo4j-5.0.9.RELEASE.jar:5.0.9.RELEASE]

这是代码

public class AppPageRequest extends PageRequest implements Pageable {

  private AppPageRequest(int page, int size, Sort sort) {
    super(page - 1, size, sort);
  }

  public static AppPageRequest of(int page, int size) {
    return of(page, size, Sort.unsorted());
  }

  public static AppPageRequest of(int page, int size, Sort sort) {
    return new AppPageRequest(page, size, sort);
  }
}

@NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends Neo4jRepository<T, ID> {

  Page<T> findAll(AppPageRequest appPageRequest);
}

@NoRepositoryBean
public class BaseRepositoryImpl<T, ID extends Serializable> extends SimpleNeo4jRepository<T, ID> implements BaseRepository<T, ID> {

  public BaseRepositoryImpl(Class<T> domainClass, Session session) {
    super(domainClass, session);
  }

  public Page<T> findAll(AppPageRequest appPageRequest) {
    return super.findAll(appPageRequest);
  }
}

2 个答案:

答案 0 :(得分:0)

假设您要确保没有人能够调用findAll并与Pageable的默认实现相关联,则需要注意两件事:

  1. 您无法覆盖findAll的签名并通过从BaseRepository扩展Neo4jRepository来进行关联,这些方法不会被覆盖而是会重载,因此可以像以前一样调用。
  2. 要使Spring Data知道您的自定义存储库实现,您必须在启用Neo4j(或任何其他存储库)时指定新的基类(如here所述)。

牢记这一点,这是一个对我们有用的解决方案。已在Java 10上运行的Spring Boot 2.0.4,Spring Data Kay和OGM 3.1.0进行了测试。在此Gist中找到完整的解决方案。

要点:

最大扩展Spring数据CrudRepository

@NoRepositoryBean
interface BaseRepository<T, ID extends Serializable> extends CrudRepository<T, ID> {
    Page<T> findAll(AppPageRequest appPageRequest);
}

CrudRepository不包含findAll,因此您的用户无法使用它。保持您的BaseRepositoryImpl不变(请参见要点)。

使您的域存储库扩展BaseRepository,而不是这样扩展Neo4jRepository

interface ThingRepository extends BaseRepository<ThingEntity, Long> {
}

这是重要的一步,通过@EnableNeo4jRepositories使SDN了解新的基本实现:

@SpringBootApplication
@EnableNeo4jRepositories(repositoryBaseClass = BaseRepositoryImpl.class)
public class CustomPagerequestApplication {

    public static void main(String[] args) {
        SpringApplication.run(CustomPagerequestApplication.class, args);
    }
}

然后您就可以像这样使用您的仓库:

@Component
class ExampleUsage implements CommandLineRunner {
    private final ThingRepository thingRepository;

    public ExampleUsage(ThingRepository thingRepository) {
        this.thingRepository = thingRepository;
    }

    @Override
    public void run(String... args) {
        var things = IntStream.iterate(1, i -> i <= 10, i -> i + 1)
            .mapToObj(ThingEntity::new)
            .collect(toList());
        this.thingRepository.saveAll(things);

        var page = this.thingRepository.findAll(AppPageRequest.of(1, 5));
        page.stream().map(ThingEntity::getName).forEach(System.out::println);
    }
}

如果有帮助,请告诉我。同样,这里是完整示例的链接: Enforce a concrete implementation of Pageable for paged Queries with Spring Data (Neo4j)

答案 1 :(得分:0)

这是配置错误。提到BaseRepositoryImpl作为存储库基类可以解决此问题。

我改变了

@EnableNeo4jRepositories

@EnableNeo4jRepositories(repositoryBaseClass = BaseRepositoryImpl.class)