简体   繁体   English

Spring 数据规范 - 带连接的 RSQL

[英]Spring Data Specifications - RSQL with join

I'm trying to develop a search API with Specification and RSQL.我正在尝试使用规范和 RSQL 开发搜索 API。 Followed this tutorial - https://www.baeldung.com/rest-api-search-language-rsql-fiql遵循本教程 - https://www.baeldung.com/rest-api-search-language-rsql-fiql

I have a User entity which have a OneToOne relation with UserProfile.我有一个与 UserProfile 有 OneToOne 关系的 User 实体。

@Entity
public class User{

    @Column(nullable = false)
    private String firstName;

    @OneToOne(targetEntity = UserProfile.class, fetch = FetchType.EAGER)
    @JoinColumn(nullable = false, name = "user_profile_id")
    private UserProfile userProfile;
...

@Entity
public class UserProfile{

    @Column(nullable = false)
    private String education;

    ...

And Predicate function,和谓词函数,

@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
    List<Object> args = castArguments(root);
    Object argument = args.get(0);

    switch (RsqlSearchOperation.getSimpleOperator(operator)) {

    case EQUAL: {
            if (argument instanceof String) {               
                return builder.like(root.get(property), argument.toString().replace('*', '%'));
            } else if (argument == null) {
                return builder.isNull(root.get(property));
            } else {
                return builder.equal(root.get(property), argument);
            }
        }
        case NOT_EQUAL: {

.... ....

When i call the API with parameter ?search=firstName==John , it's returning results as expected.当我使用参数 ?search=firstName==John 调用 API 时,它会按预期返回结果。 What i need is search by education and return Users having that education.我需要的是按教育搜索并返回具有该教育的用户。 I tried with Join as follows, but it's not working.我尝试使用 Join 如下,但它不起作用。

if (argument instanceof String) {
                Join<User, UserProfile> profileJoin = root.join("user_profile_id");

                return builder.like(root.get(property), profileJoin.get(property));
            } else if (argument == null) {

Any solution with generic will be really helpful.任何具有泛型的解决方案都会非常有帮助。

Looks like there is no concrete solution with generic.看起来泛型没有具体的解决方案。 So i did it which is close to being generic.所以我做到了,这接近于通用。

switch (RsqlSearchOperation.getSimpleOperator(operator)) {

        case EQUAL: {
            if (doesClassContainProperty(UserProfile.class, property)) {
                Join<User, UserProfile> profileJoin = root.join("user_profile_id");
                return builder.equal(profileJoin.get(property), argument);
            } else {
                return builder.equal(root.get(property), argument);
            }
        }

And here is the method to check whether passed param is in root class or join class这是检查传递的参数是否在根类或加入类中的方法

public boolean doesClassContainProperty(Class<?> genericClass, String fieldName) {
        return Arrays.stream(genericClass.getDeclaredFields()).anyMatch(f -> f.getName().equals(fieldName));
    }

I would like to recommend you another library, which lets you build dynamic filters without having to mess with coding, it supports logical operators, comparators, enums, dates, booleans, searching over relations/joins (no n+1 query problem), functions, and much more: https://github.com/turkraft/spring-filter我想向您推荐另一个库,它可以让您构建动态过滤器而不必弄乱编码,它支持逻辑运算符、比较器、枚举、日期、布尔值、搜索关系/连接(没有 n+1 查询问题)、函数,以及更多: https : //github.com/turkraft/spring-filter

Example query:示例查询:

/search?filter= average (ratings) > 4.5 and brand.name in ('audi', 'land rover') and (year > 2018 or km < 50000) and color : 'white' and accidents is empty /search?filter= average (ratings) > 4.5 and brand.name in ('audi', 'land rover') and (year > 2018 or km < 50000) and color : 'white' and notices is empty

Usage:用法:

@GetMapping(value = "/search")
public List<Entity> search(@EntityFilter Specification<Entity> spec, Pageable page) {
  return repo.findAll(spec, page);
}

Don't forget the dependency:不要忘记依赖:

<dependency>
    <groupId>com.turkraft</groupId>
    <artifactId>spring-filter</artifactId>
    <version>0.9.5</version>
</dependency>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM