【问题标题】:querydsl-jpa dynamic queryquerydsl-jpa 动态查询
【发布时间】:2017-04-06 00:38:21
【问题描述】:

假设我有一个这样的生成实体:

public class QCandidate extends EntityPathBase<Candidate> {

public final com.avisto.candisearch.persistance.model.enums.QAvailabilityEnum availability;

public final DatePath<java.util.Date> birthDate = createDate("birthDate", java.util.Date.class);

public final NumberPath<Long> cvId= createNumber("cvId", Long.class);

public final StringPath city = createString("city");

}

我的输入值是字段名称(“availability”、“birthDate”、“cvId”...)和一个字符串值,我应该使用它来对所有字段执行“点赞”。

我想从以下字段名称开始构建查询:

  • 将日期和数字转换为字符串并将它们小写
  • 如果字段是 EntityPathBase(如可用性),则提取 id,然后再次转换为小写字符串

类似:

lower(cast(C.cvId as varchar(255))) like 'value'

每个字段。

我可以使用 querydsl-sql 模块来实现,但我想只使用 jpa 模块来实现它。

我对创建 FULL 'where' 子句的机制不感兴趣(我知道我必须使用 BooleanBuilder,或者至少,这是我在 sql 版本中所做的)。

我想知道的是如何根据字段类型创建单独的“位置”条件。

我正在尝试使用 PathBuilder,但似乎要使用“getString 或 getBoolean”之类的方法,您已经必须知道要提取的字段的类型。就我而言,由于我只是从字段名开始,我无法使用这些方法,并且我不知道如何识别从字段名开始的每个字段的类型,所以我卡住了。

【问题讨论】:

    标签: java jpql querydsl


    【解决方案1】:

    可能有点难看,但可行的建议。

    请注意,PathBuilder 接受的字段类型数量非常有限。

    您绝对可以从字段名称中找到字段类(使用反射或通过维护每个字段更新的成员映射)。

    只需为每个特定类型实现处理。

    这可能是一堆丑陋的if..else,或者,为了更优雅的解决方案,创建类型处理程序 [class->handler] 的 Map,每个处理程序实现接口方法来处理特定类型。

    伪代码:

    //building query
    for each field
      Class fieldClass = findFieldClas(.., field) //use reflection or map
      PathHandler handler = handlers.get(fieldClass)
      handler.process( ...)
    
    //type handler interface
    public interface Handler{
      public xx process(? extends DataPathBase);
    }
    
    //specific type handler implementation
    public class BooleanHandler implements Handler{
      public xx process(? extends DataPathBase path){
        BooleanPath bPath = (BooleanPath)path;
        ...
    }
    
    //intitialize handlers map singleton or a factory in advance    
    handlers.put(BooleanPath.class, new BooleanHandler());
    ...
    

    请注意,如果您有很多类,这是一个通用的解决方案。如果你只有一个特定的类,你可以创建一个 fieldName->Handler 的永久映射,避免查找字段类。

    同样,这绝不是一个很好的解决方案,但应该可以。

    【讨论】:

    • 感谢您的回答,但我想避免“硬编码”任何类型的映射。我觉得没有那个我应该能够做我想做的事......:/
    • 我不会称之为“硬编码”。 DatePathBase 的集合非常有限,并且即使有,也很少会随着库升级而改变。另外,如果你在处理的字段中升级后不使用新类型,你不需要更新任何东西,基本上是一次工作。您不是将字段名称映射到处理程序,而是映射字段类型,因此它更像是一种“框架”,而不是硬编码处理,是 API 的薄抽象层。
    • 你是对的,内省绝对是正确的方法。愚蠢的我没有想到它:) 谢谢。
    猜你喜欢
    • 1970-01-01
    • 2014-03-29
    • 2020-03-15
    • 2017-12-22
    • 2015-05-11
    • 2015-10-22
    • 2012-07-25
    • 2020-10-06
    • 1970-01-01
    相关资源
    最近更新 更多