我正在尝试使用规范和RSQL开发搜索API。遵循了本教程-https://www.baeldung.com/rest-api-search-language-rsql-fiql
我有一个与UserProfile具有OneToOne关系的User实体。
@Entity
public class User{
@Column(nullable = false)
private String firstName;
@OneToOne(targetEntity = UserProfile.class, fetch = FetchType.EAGER)
@JoinColumn(nullable = false, name = "user_profile_id")
private UserProfile userProfile;
...
@Entity
public class UserProfile{
@Column(nullable = false)
private String education;
...
和谓词功能,
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
List<Object> args = castArguments(root);
Object argument = args.get(0);
switch (RsqlSearchOperation.getSimpleOperator(operator)) {
case EQUAL: {
if (argument instanceof String) {
return builder.like(root.get(property), argument.toString().replace('*', '%'));
} else if (argument == null) {
return builder.isNull(root.get(property));
} else {
return builder.equal(root.get(property), argument);
}
}
case NOT_EQUAL: {
....
当我使用参数?search = firstName == John调用API时,它会按预期返回结果。我需要的是按教育程度搜索,然后返回受过教育的用户。我尝试了Join,如下所示,但它不起作用。
if (argument instanceof String) {
Join<User, UserProfile> profileJoin = root.join("user_profile_id");
return builder.like(root.get(property), profileJoin.get(property));
} else if (argument == null) {
任何具有泛型的解决方案都将非常有用。
最佳答案
似乎没有通用的具体解决方案。所以我做到了,这几乎是通用的。
switch (RsqlSearchOperation.getSimpleOperator(operator)) {
case EQUAL: {
if (doesClassContainProperty(UserProfile.class, property)) {
Join<User, UserProfile> profileJoin = root.join("user_profile_id");
return builder.equal(profileJoin.get(property), argument);
} else {
return builder.equal(root.get(property), argument);
}
}
这是检查传递的参数是在根类中还是在连接类中的方法
public boolean doesClassContainProperty(Class<?> genericClass, String fieldName) {
return Arrays.stream(genericClass.getDeclaredFields()).anyMatch(f -> f.getName().equals(fieldName));
}
关于java - Spring数据规范-带联接的RSQL,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57100185/