I am trying to use listagg function to generate a list of users.
Consider the following table
ROLE_ID ENAME
---------- ----------
4 CLARK
4 KING
4 MILLER
7 ADAMS
9 FORD
9 JONES
On using the following query in the SQL Developer
SELECT ROLE_ID,
LISTAGG(ENAME, ',') WITHIN GROUP (ORDER BY ENAME) AS EMPLOYEES
FROM USERS
GROUP BY ROLE_ID;
will result in the following in the console output
ROLE_ID EMPLOYEES
-----------------------------
4 CLARK,KING,MILLER
7 ADAMS
9 FORD, JONES
My goal is try doing this in hibernate but I am not sure how to proceed. Any help is appreciated.
The LISTAGG function is used to aggregate a set of string values within a group into a single string by appending the string-expression values based on the order that's specified in the 'WITHIN GROUP' clause. As a single-set aggregate function, LISTAGG operates on all rows and returns a single output row.
Basic usage of Oracle LISTAGG() function For example, the following query returns a comma-separated list of employees for each job title. In this example, the LISTAGG() function concatenates the first names of employees who have the same job title.
In order to concatenate field values, I would use “GROUP_CONCAT” function in Virtual DataPort Administration tool which is similar to LISTAGG function. For example, GROUP_CONCAT('<row separator>',<field_name>)
Listagg is an ordered set function, which require the within group clause to specify an order. The minimal syntax is: LISTAGG(<expression>, <separator>) WITHIN GROUP(ORDER BY …) The <expression> must not contain window functions, aggregate functions or subqueries.
For anyone having problems using listagg as part of a formula, registering the "within" keyword with Hibernate solved the problem for me. (Using Hibernate 5.0.7.)
public class CustomOracleDialect extends Oracle10gDialect {
public CustomOracleDialect() {
super();
registerKeyword("within");
}
}
Prior to this, Hibernate would break the query by attempting to prefix the "within" keyword with the outer table's alias. Once the keyword was registered the following works:
@Formula("(select (listagg(l.serial_number, ', ') within group(order by d.serial_number))\n"
+ "from order_lines l\n"
+ "where l.order_id = id\n"
+ "group by l.order_id)")
private String serialNumbers;
Note that if you try to assign an alias to the listagg expression it still breaks the query, as Hibernate tries to prepend it with the table's alias as well. This of course is not an issue with formula queries, but if using listagg as part of a named query you may need to omit the alias and reference the column by position within the result set.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With