我正在设置repository
来电,以检索ids
中使用的测试结果GROUP_BY
列表的ID。我可以使用createNativeQuery
来解决此问题,但我无法通过JPA
调用使用Spring FUNCTION
来实现此功能。
FUNCTION('string_agg', FUNCTION('to_char',r.id, '999999999999'), ',')) as ids
我正在使用Spring Boot 1.4,hibernate和PostgreSQL。
问题
更新1
实现自定义方言后,看起来它试图将函数转换为long
。功能代码是否正确?
FUNCTION('string_agg', FUNCTION('to_char',r.id, '999999999999'), ','))
更新2
在进一步查看方言后,您似乎需要为您的函数注册返回类型,否则它将默认为long
。请参阅下面的解决方案。
这是我的代码:
DTO
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TestScriptErrorAnalysisDto {
private String testScriptName;
private String testScriptVersion;
private String checkpointName;
private String actionName;
private String errorMessage;
private Long count;
private String testResultIds;
}
控制器
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<Set<TestScriptErrorAnalysisDto>> getTestScriptErrorsByExecutionId(@RequestParam("executionId") Long executionId) throws Exception {
return new ResponseEntity<Set<TestScriptErrorAnalysisDto>>(testScriptErrorAnalysisRepository.findTestScriptErrorsByExecutionId(executionId), HttpStatus.OK);
}
存储库尝试使用功能不工作
@Query(value = "SELECT new com.dto.TestScriptErrorAnalysisDto(r.testScriptName, r.testScriptVersion, c.name, ac.name, ac.errorMessage, count(*) as ec, FUNCTION('string_agg', FUNCTION('to_char',r.id, '999999999999'), ',')) "
+ "FROM Action ac, Checkpoint c, TestResult r " + "WHERE ac.status = 'Failed' " + "AND ac.checkpoint = c.id " + "AND r.id = c.testResult " + "AND r.testRunExecutionLogId = :executionId "
+ "GROUP by r.testScriptName, r.testScriptVersion, c.name, ac.name, ac.errorMessage " + "ORDER by ec desc")
Set<TestScriptErrorAnalysisDto> findTestScriptErrorsByExecutionId(@Param("executionId") Long executionId);
使用createNativeQuery 工作
的存储库 List<Object[]> errorObjects = entityManager.createNativeQuery(
"SELECT r.test_script_name, r.test_script_version, c.name as checkpoint_name, ac.name as action_name, ac.error_message, count(*) as ec, string_agg(to_char(r.id, '999999999999'), ',') as test_result_ids "
+ "FROM action ac, checkpoint c, test_result r " + "WHERE ac.status = 'Failed' " + "AND ac.checkpoint_id = c.id "
+ "AND r.id = c.test_result_id " + "AND r.test_run_execution_log_id = ? "
+ "GROUP by r.test_script_name, r.test_script_version, c.name, ac.name, ac.error_message " + "ORDER by ec desc")
.setParameter(1, test_run_execution_log_id).getResultList();
for (Object[] obj : errorObjects) {
for (Object ind : obj) {
log.debug("Value: " + ind.toString());
log.debug("Value: " + ind.getClass());
}
}
以下是我在FUNCTION上找到的文件
4.6.17.3 Invocation of Predefined and User-defined Database Functions
The invocation of functions other than the built-in functions of the Java Persistence query language is supported by means of the function_invocation syntax. This includes the invocation of predefined database functions and user-defined database functions.
function_invocation::= FUNCTION(function_name {, function_arg}*)
function_arg ::=
literal |
state_valued_path_expression |
input_parameter |
scalar_expression
The function_name argument is a string that denotes the database function that is to be invoked. The arguments must be suitable for the database function that is to be invoked. The result of the function must be suitable for the invocation context.
The function may be a database-defined function or a user-defined function. The function may be a scalar function or an aggregate function.
Applications that use the function_invocation syntax will not be portable across databases.
Example:
SELECT c
FROM Customer c
WHERE FUNCTION(‘hasGoodCredit’, c.balance, c.creditLimit)
答案 0 :(得分:0)
最后,缺少的主要部分是通过创建一个新类来扩展PostgreSQL94Dialect来定义函数。由于没有为方言定义这些功能,因此不会在通话中处理这些功能。
public class MCBPostgreSQL9Dialect extends PostgreSQL94Dialect {
public MCBPostgreSQL9Dialect() {
super();
registerFunction("string_agg", new StandardSQLFunction("string_agg", new org.hibernate.type.StringType()));
registerFunction("to_char", new StandardSQLFunction("to_char"));
registerFunction("trim", new StandardSQLFunction("trim"));
}
}
另一个问题是需要为注册时函数的返回类型设置类型。我得到了long
,因为默认情况下registerFunction
会返回long
,即使string_agg会在postgres的sql查询中返回一个字符串。
使用new org.hibernate.type.StringType()
更新后,它有效。
registerFunction("string_agg", new StandardSQLFunction("string_agg", new org.hibernate.type.StringType()));