querydsl-jpa 动态查询
querydsl-jpa dynamic query
假设我有一个这样生成的实体:
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"...)和我应该用来执行 'like' 的字符串值包含所有字段。
我想从以下字段名称开始构建查询:
- 将日期和数字转换为字符串并将其小写
- 如果该字段是 EntityPathBase(如可用性),则提取 id,然后再次转换为小写字符串
类似于:
lower(cast(C.cvId as varchar(255))) like 'value'
每个字段。
我可以做这个 usign querydsl-sql 模块,但我想只使用 jpa 模块来实现它。
我对创建 FULL 'where' 子句的机制不感兴趣(我知道我必须使用 BooleanBuilder,或者至少,这是我在 sql 版本中所做的).
我想知道的是如何根据字段类型创建单独的 'where' 条件。
我正在尝试使用 PathBuilder,但似乎要使用像 "getString or getBoolean" 这样的方法,您已经必须知道您要提取的字段的类型。就我而言,由于我只是从字段名开始,我不能使用这些方法,我不知道如何从字段名开始识别每个字段的类型,所以我被卡住了。
可能有点难看,但可行的建议。
请注意,PathBuilder 接受的字段类型数量非常有限。
您绝对可以从字段名称中找到字段 class(使用反射或通过维护每个字段更新的成员映射)。
只需针对每个特定类型实施处理。
这可能是一堆丑陋的 if..else
或者,为了更优雅的解决方案,创建类型处理程序的映射 [class->handler],每个处理程序实现接口方法来处理特定类型。
伪代码:
//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());
...
请注意,如果您有很多 class,这是一个通用的解决方案。如果你只有一个特定的 class,你可以只创建一个 fieldName->Handler 的永久映射并避免查找字段 class.
同样,这绝不是一个很好的解决方案,但应该可行。
假设我有一个这样生成的实体:
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"...)和我应该用来执行 'like' 的字符串值包含所有字段。
我想从以下字段名称开始构建查询:
- 将日期和数字转换为字符串并将其小写
- 如果该字段是 EntityPathBase(如可用性),则提取 id,然后再次转换为小写字符串
类似于:
lower(cast(C.cvId as varchar(255))) like 'value'
每个字段。
我可以做这个 usign querydsl-sql 模块,但我想只使用 jpa 模块来实现它。
我对创建 FULL 'where' 子句的机制不感兴趣(我知道我必须使用 BooleanBuilder,或者至少,这是我在 sql 版本中所做的).
我想知道的是如何根据字段类型创建单独的 'where' 条件。
我正在尝试使用 PathBuilder,但似乎要使用像 "getString or getBoolean" 这样的方法,您已经必须知道您要提取的字段的类型。就我而言,由于我只是从字段名开始,我不能使用这些方法,我不知道如何从字段名开始识别每个字段的类型,所以我被卡住了。
可能有点难看,但可行的建议。
请注意,PathBuilder 接受的字段类型数量非常有限。
您绝对可以从字段名称中找到字段 class(使用反射或通过维护每个字段更新的成员映射)。
只需针对每个特定类型实施处理。
这可能是一堆丑陋的 if..else
或者,为了更优雅的解决方案,创建类型处理程序的映射 [class->handler],每个处理程序实现接口方法来处理特定类型。
伪代码:
//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());
...
请注意,如果您有很多 class,这是一个通用的解决方案。如果你只有一个特定的 class,你可以只创建一个 fieldName->Handler 的永久映射并避免查找字段 class.
同样,这绝不是一个很好的解决方案,但应该可行。