Mysql
 sql >> база данни >  >> RDS >> Mysql

Ключовата дума SEPARATOR не работи правилно във формула за хибернация

Можете да добавите 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;
    }
}

Същото за версиите на Hibernate преди 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;
    }

}

След това ще трябва да кажете на Hibernate да използва вашия диалектен разделител. Например в JPA можете да направите това във вашия persistence.xml:

<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 / Criteria заявки, без да мислите за синтаксиса на диалекта:

 SELECT e.group, listagg(e.stringProperty, ', ') FROM Entity e GROUP BY e.group



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. INSERT INTO...SELECT за всички MySQL колони

  2. Най-добрият начин да тествате дали в MySQL таблица съществува ред

  3. Извличане на повече от 3 данни от mysql в квадратчето за отметка

  4. Извличане на подниз на MySQL с помощта на разделител

  5. Пренаписването на URL с .htaccess прави дублирани записи в mysql