आप SEPARATOR
जोड़ सकते हैं कीवर्ड के रूप में। अपना खुद का DialectResolver
लागू करें और कीवर्ड छोटे अक्षरों में जोड़ें परिणामी बोली के लिए:
public class MyDialectResolver implements DialectResolver {
public Dialect resolveDialect(DialectResolutionInfo info) {
for (Database database : Database.values()) {
Dialect dialect = database.resolveDialect(info);
if (dialect != null) {
dialect.getKeywords().add("separator");
return dialect;
}
}
return null;
}
}
हाइबरनेट संस्करणों के लिए पहले . के लिए भी ऐसा ही है 5.2.13 / 5.3.0:
public class MyDialectResolver extends StandardDialectResolver {
protected Dialect resolveDialectInternal(DatabaseMetaData metaData) throws SQLException {
Dialect dialect = super.resolveDialectInternal(metaData);
dialect.getKeywords().add("separator");
return dialect;
}
}
फिर आपको हाइबरनेट को अपनी बोली रिज़ॉल्वर का उपयोग करने के लिए कहना होगा। उदाहरण के लिए जेपीए में आप इसे अपने हठ में कर सकते हैं।एक्सएमएल:
<persistence>
<persistence-unit>
...
<property name="hibernate.dialect_resolvers" value="mypackage.MyDialectResolver"/>
</persistence-unit>
</persistence>
यही बात अन्य बोलियों में एकत्रीकरण कार्यों पर भी लागू होती है। उदाहरण के लिए Oracle में WITHIN
कीवर्ड गुम है।
एक और विकल्प है, जो अधिक डेटाबेस स्वतंत्र है (और जिसे मैं पसंद करता हूं)। निम्नलिखित SQLFunction
बनाएं :
public class ListAggFunction implements SQLFunction {
/**
* The pattern that describes how the function is build in SQL.
*
* Replacements:
* {path} - is replaced with the path of the list attribute
* {separator} - is replaced with the separator (defaults to '')
* {orderByPath} - is replaced by the path that is used for ordering the elements of the list
*/
private String pattern;
/**
* Creates a new ListAggFunction definition which uses the ANSI SQL:2016 syntax.
*/
public ListAggFunction() {
this("LISTAGG(DISTINCT {path}, {separator}) WITHIN GROUP(ORDER BY {orderByPath})");
}
/**
* Creates a new ListAggFunction definition which uses a database specific syntax.
*
* @param pattern The pattern that describes how the function is build in SQL.
*/
public ListAggFunction(String pattern) {
this.pattern = pattern;
}
public Type getReturnType(Type firstArgumentType, Mapping mapping) throws QueryException {
return StringType.INSTANCE;
}
public boolean hasArguments() {
return true;
}
public boolean hasParenthesesIfNoArguments() {
return true;
}
public String render(Type firstArgumentType, List arguments,
SessionFactoryImplementor factory) throws QueryException {
if (arguments.isEmpty() || arguments.size() > 3) {
throw new IllegalArgumentException(
"Expected arguments for 'listagg': path [, separator [, order by path]]");
}
String path = (String) arguments.get(0);
String separator = arguments.size() < 2 ? "''" : (String) arguments.get(1);
String orderByPath = arguments.size() <= 2 ? path : (String) arguments.get(2);
return StringUtils.replaceEach(this.pattern, new String[] { "{path}", "{separator}", "{orderByPath}" },
new String[] { path, separator, orderByPath });
}
}
आप ऊपर दिए गए कीवर्ड की तरह ही इस फ़ंक्शन को DialectResolver में पंजीकृत कर सकते हैं:
if ("MySQL".equals(info.getDatabaseName()) || "H2".equals(info.getDatabaseName())) {
dialect.getFunctions().put("listagg", new ListAggFunction("GROUP_CONCAT(DISTINCT {path} ORDER BY {orderByPath} SEPARATOR {separator})"));
} else {
dialect.getFunctions().put("listagg", new ListAggFunction());
}
अब आप बोली के सिंटैक्स के बारे में सोचे बिना अपने JPQL / HQL / मानदंड प्रश्नों में इस फ़ंक्शन का उपयोग कर सकते हैं:
SELECT e.group, listagg(e.stringProperty, ', ') FROM Entity e GROUP BY e.group