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

Posted

技术标签:

【中文标题】在 Spring Data 中为同一 QueryDSL 路径创建多个别名【英文标题】:Creating multiple aliases for the same QueryDSL path in Spring Data 【发布时间】:2017-05-30 18:08:45 【问题描述】:

我有一个扩展 QuerydslBinderCustomizer 的通用 Spring Data 存储库接口,允许我自定义查询执行。我正在尝试扩展默认存储库实现中内置的基本相等测试,以便我可以使用 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);
                        );
            
        
    

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

【问题讨论】:

挖掘源代码似乎绑定存储在由路径键控的 Map 中:private final Map&lt;String, PathAndBinding&lt;?, ?&gt;&gt; pathSpecs 这可以解释为什么 bindings.bind(Expressions.stringPath(root, field.getName())) 会覆盖以前的绑定。但是不知道是否有其他方法可以实现这一点。 检查这个关于类似问题的其他答案:***.com/a/43852346/5747715 基本上,您需要创建更多字段(未持久化)以将功能附加到它们。 现在有简单的方法吗?像这样的限制使得使用 querydsl 很困难 看起来您正在尝试提供通用搜索 api。如果是这样,请检查 rsql 解析器和 rsql-jpa。 @Adi:我最终实现的很像 RSQL。如果 Spring Data 和 QueryDSL 在这方面更加灵活就好了。 【参考方案1】:

您可以通过这种方式创建绑定到 QueryDSL 的瞬态属性:

@Transient
@QueryType(PropertyType.SIMPLE)
public String getNameEndsWith() 
    // Whatever code, even return null

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

【讨论】:

以上是关于在 Spring Data 中为同一 QueryDSL 路径创建多个别名的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Boot / Spring Data 中为 Amazon RDS Mysql 启用 SSL?

无法在 SpEL 中为 Spring Data MongoDB 集合名称解析 bean

如果在 Spring Data JPA 中为空或为空,如何在 @Query 中跳过 @Param

spring-data-mongodb 在一个 Mongo 实例中连接多个数据库

如何在spring data jpa中为自定义采石场提供可变参数而不使用for循环

如何在 Spring Boot 应用程序的同一个域类上同时使用 Spring Data JPA 和 Spring Data Elasticsearch 存储库?