在Spring Data中为相同的QueryDSL路径创建多个别名

45

我有一个通用的Spring Data仓库接口,它扩展了QuerydslBinderCustomizer,使我能够自定义查询执行。我正在尝试扩展默认仓库实现中内置的基本相等性测试,以便我可以使用Spring Data REST执行其他查询操作。例如:

GET /api/persons?name=Joe%20Smith  // This works by default
GET /api/persons?nameEndsWith=Smith  // This requires custom parameter binding.

我遇到的问题是,我创建的每个实体路径的别名似乎都会覆盖先前的别名绑定。
@NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable>
    extends PagingAndSortingRepository<T, ID>, QueryDslPredicateExecutor<T>, QuerydslBinderCustomizer { 

    @Override
    @SuppressWarnings("unchecked")
    default void customize(QuerydslBindings bindings, EntityPath entityPath){

        Class<T> model = entityPath.getType();
        Path<T> root = entityPath.getRoot();
        for (Field field: model.getDeclaredFields()){
            if (field.isSynthetic()) continue;
            Class<?> fieldType = field.getType();
            if (fieldType.isAssignableFrom(String.class)){
                // This binding works by itself, but not after the next one is added
                bindings.bind(Expressions.stringPath(root, field.getName()))
                        .as(field.getName()  + "EndsWith")
                        .first((path, value) -> {
                            return path.endsWith(value);
                        });
                // This binding overrides the previous one
                bindings.bind(Expressions.stringPath(root, field.getName()))
                        .as(field.getName()  + "StartsWith")
                        .first((path, value) -> {
                            return path.startsWith(value);
                        });
            }
        }
    }
}

是否可以为同一字段创建多个别名?这可以以通用的方式完成吗?


2
通过查看源代码,似乎绑定是存储在一个以路径为键的Map中:private final Map<String, PathAndBinding<?, ?>> pathSpecs,这就解释了为什么bindings.bind(Expressions.stringPath(root, field.getName()))会覆盖先前的绑定。不过我不知道是否有其他方法可以实现这个功能。 - Alan Hay
1
请查看关于类似问题的另一个答案:https://dev59.com/EVsW5IYBdhLWcg3wSVqM#43852346 基本上,您需要创建更多字段(不会被持久化)来附加功能。 - Jorge C
1
现在有没有简单的方法可以做到这一点?像这样的限制使得使用querydsl变得困难。 - Charlie
1
看起来你正在尝试提供通用搜索API。如果是这样,请检查RSQL解析器和RSQL-JPA。 - Adisesha
2
@Adi:我最终实现的很像RSQL。如果Spring Data和QueryDSL在这方面更加灵活就好了。 - woemler
@woemler,为了扭转局面,看起来需要使用一些操作符,例如/search/users?emails.value=endsWith(@company.com)&emails.value=endsWith(@legacycompany.com),有一个项目可以提供这些操作符:https://gt-tech.bitbucket.io/spring-data-querydsl-value-operators/README.html。 - hakamairi
1个回答

1
您可以通过以下方式创建一个绑定到QueryDSL的瞬态属性:
@Transient
@QueryType(PropertyType.SIMPLE)
public String getNameEndsWith() {
    // Whatever code, even return null
}

如果您正在使用QueryDSL注释处理器,您将在元数据Qxxx类中看到"nameEndsWith",因此您可以像绑定任何持久化属性一样绑定它,但不需要将其持久化。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接