英文:
Type safe way to go from a String to a Strategy with Jackson
问题
我想执行带有过滤器的查询,从 UI 开始,基于逻辑运算符 (>20)。
目前,逻辑运算符 (匹配器) 是 Jackson 映射到枚举的常量。
然后我有一个大型的模式匹配开关,将每个枚举映射到一个函数。
使用 Hibernate Criteria Builder 生成谓词的函数。
这通常是一个实用的简单解决方案,但是长长的开关语句最终会变得难以管理。
地图查找也没有更好,因为你必须首先将地图配置为大块文本,本质上与大型模式匹配开关没有区别。
因此,我正在寻找一种安全的方式,可以从 JSON 文件中的字符串转换为具体的实现策略,例如从 "TEXT_EQUALS_" 到 TextEqualsMatcher,它可以使用 CriteriaBuilder 方法参数构建 Hibernate 谓词。
是的,这将强烈地将 JSON 与 Hibernate 耦合起来 - 但我认为无论如何都存在耦合,因为我们有数据库过滤器 - 在我看来,一个非常精简的实现没有任何查找的优点可能会证明其合理性。
所以基本上我正在寻找一种从这个安全类型的方法:
{
"type": "field",
"id": "104e578c-6841-48e5-8ee0-927a1eaa0fbe",
"value": "Ukraine",
"matcher": "text_equals"
}
到这个的方式:
public class TextEqualsMatcher implements FieldMatcher {
@Override
public Predicate toPredicate(CriteriaBuilder cb, Path<String> path) {
// 构建并返回 Text Equals 条件的谓词的逻辑
}
}
代码可能是这样的:
public interface Filter {
Predicate toPredicate(CriteriaBuilder cb, Path<String> path);
}
@JsonTypeName("field")
public record FieldElement(
@JsonProperty("id") UUID id,
@JsonProperty("value") String value,
@JsonProperty("matcher") FieldMatcher matcher
) implements Filter {
public Predicate toPredicate(CriteriaBuilder cb, Path<String> path) {
return matcher.toPredicate(cb, path, value);
}
}
public interface FieldMatcher {
Predicate toPredicate(CriteriaBuilder cb, Path<String> path, String value);
}
@JsonTypeName("text_equals")
public class TextEqualsMatcher implements FieldMatcher {
public Predicate toPredicate(CriteriaBuilder cb, Path<String> path, String value) {
// 构建并返回 Text Equals 条件的谓词的逻辑
}
}
所以我猜一个带有 Enum 常量的 @JsonTypeName 将会很棒:
@JsonTypeName(MatcherType.TEXT_EQUALS)
任何输入/想法?
英文:
I want to execute queries with filters, from UI, based on logical operators (>20).
Currently, the logical operator (matcher) is a constant that Jackson maps to an enum.
Then I have a large pattern-matching switch that then maps each enum to a function.
A function that generates a predicate using the Hibernate Criteria Builder.
This is generally a pragmatic simple solution - but the long switch statement eventually will become unmanageable.
A map lookup is no better because you would have to configure the map as big block of text first, which in essence is no different from a large pattern matching switch.
So I am looking for a type-safe way to go from a string in a json file to the concrete
implementing strategy, e.g from "TEXT_EQUALS_ to a TextEqualsMatcher that can build a Hibernate Predicate with a CriteriaBuilder method parameter.
Yes, this would strongly couple json to Hibernate -
but I think the coupling is there anyway, one way or another because we have database filters - and IMHO the advantages of a very lean implementation without any lookup could justify it
So basically I am looking for a type-safe way to go from this:
{
"type": "field",
"id": "104e578c-6841-48e5-8ee0-927a1eaa0fbe",
"value": "Ukraine",
"matcher": "text_equals"
}
to this:
public class TextEqualsMatcher implements FieldMatcher {
@Override
public Predicate toPredicate(CriteriaBuilder cb, Path<String> path) {
// Logic to build and return the predicate for the Text Equals condition
}
}
The code would probably be something like this:
public interface Filter {
Predicate toPredicate(CriteriaBuilder cb, Path<String> path);
}
@JsonTypeName("field")
public record FieldElement(
@JsonProperty("id") UUID id,
@JsonProperty("value") String value,
@JsonProperty("matcher") FieldMatcher matcher
) implements Filter {
public Predicate toPredicate(CriteriaBuilder cb, Path<String> path) {
return matcher.toPredicate(cb, path, value);
}
}
public interface FieldMatcher {
Predicate toPredicate(CriteriaBuilder cb, Path<String> path, String value);
}
@JsonTypeName("text_equals")
public class TextEqualsMatcher implements FieldMatcher {
public Predicate toPredicate(CriteriaBuilder cb, Path<String> path, String value) {
// Logic to build and return the predicate for the Text Equals condition
}
}
So a @JsonTypeName with an Enum constant would be great I guess:
@JsonTypeName(MatcherType.TEXT_EQUALS)
Any input/ideas?
答案1
得分: 1
这似乎是可行的:您确实需要在基接口中添加@JsonTypeInfo
(以指示多态处理),并且还需要从基类型到子类型的@JsonSubTypes
引用(这有点不太幸运)。
但是有了这些,似乎事情应该可以工作?
英文:
It seems doable: you do need to add @JsonTypeInfo
in base interfaces (to indicate polymorphic handling), and also @JsonSubTypes
references from base- to sub-types (which is bit unfortunate).
But with that it seems things should work?
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论