gpt4 book ai didi

java - 以列表作为参数的 spring-data 查询方法

转载 作者:行者123 更新时间:2023-11-30 11:33:15 25 4
gpt4 key购买 nike

我们必须从数据库中查询数据,我们需要在其中找到与键值对列表匹配的实体。我们认为使用 Spring Data JPA 是个好主意,因为我们还需要分页。

我们创建的表格如下:

terminal(ID,NUMBER,NAME);
terminal_properties(ID,KEY,VALUE,TERMINAL_FK);

是否可以定义一个查询方法来获取所有具有包含给定键/值对的属性的终端?

像这样:List findByPropertiesKeyAndValue(List );

最佳答案

我没有执行代码,但给出正确的导入语句,这至少可以编译。根据您的实体定义,某些属性可能需要调整,无论如何,您应该了解如何处理这个问题。

我的条件查询基于以下 SQL:

SELECT * FROM TERMINAL
WHERE ID IN (
SELECT TERMINAL_FK FROM TERMINAL_PROPERTIES
WHERE (KEY = 'key1' AND VALUE = 'value1')
OR (KEY = 'key2' AND VALUE = 'value2')
...
GROUP BY TERMINAL_FK
HAVING COUNT(*) = 42
)

在其中列出每个名称/值对和 42简单地表示名称/值对的数量。

所以我假设您定义了这样一个存储库:

public interface TerminalRepository extends CrudRepository<Terminal, Long>, JpaSpecificationExecutor {
}

扩展 JpaSpecificationExecutor 很重要以便使用标准 API。

然后您可以像这样构建条件查询:

public class TerminalService {

private static Specification<Terminal> hasProperties(final Map<String, String> properties) {
return new Specification<Terminal>() {
@Override
public Predicate toPredicate(Root<Terminal> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
// SELECT TERMINAL_FK FROM TERMINAL_PROPERTIES
Subquery<TerminalProperty> subQuery = query.subquery(TerminalProperty.class);
Root propertyRoot = subQuery.from(TerminalProperty.class);
subQuery.select(propertyRoot.get("terminal.id"));
Predicate whereClause = null;
for (Map.Entry<String, String> entry : properties.entrySet()) {
// (KEY = 'key1' AND VALUE = 'value1')
Predicate predicate = builder.and(builder.equal(propertyRoot.get("key"),
entry.getKey()), builder.equal(propertyRoot.get("value"), entry.getValue()));
if (whereClause == null) {
whereClause = predicate;
} else {
// (...) OR (...)
whereClause = builder.or(whereClause, predicate);
}
}
subQuery.where(whereClause);
// GROUP BY TERMINAL_FK
subQuery.groupBy(propertyRoot.get("terminal.id"));
// HAVING COUNT(*) = 42
subQuery.having(builder.equal(builder.count(propertyRoot), properties.size()));

// WHERE ID IN (...)
return query.where(builder.in(root.get("id")).value(subQuery)).getRestriction();
}
};
}

@Autowired
private TerminalRepository terminalRepository;

public Iterable<Terminal> findTerminalsWith(Map<String, String> properties) {
// this works only because our repository implements JpaSpecificationExecutor
return terminalRepository.findAll(hasProperties(properties));
}
}

您显然可以替换 Map<String, String>Iterable<TerminalProperty> ,虽然这会让人觉得奇怪,因为它们似乎绑定(bind)到特定的 Terminal .

关于java - 以列表作为参数的 spring-data 查询方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16174291/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com