es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Hacer que la función convert_tz de MySQL funcione en una base de datos H2.

Estoy escribiendo una prueba en una base de datos en memoria bajo un H2 que utiliza el dialecto de MySQL (org.hibernate.dialect.MySQL5InnoDBDialect), ya que lo utilizamos en producción.

En uno de los repositorios tenemos una consulta personalizada con el siguiente bloque:

DATE(CONVERT_TZ(NOW(), 'GMT', (:timezoneOffset)))

Sin embargo, H2 arroja el siguiente error:

org.h2.jdbc.JdbcSQLSyntaxErrorException: Función "convert_tz" no encontrada;

Intenté las soluciones sugeridas en esta publicación:
https://stackoverflow.com/questions/31725820/how-to-use-the-mysql-convert-tz-function-in-a-jpql-or-hql-query/31741171

También intenté con un SQLFunctionTemplate como se muestra en estos ejemplos: https://www.tabnine.com/code/java/methods/org.hibernate.boot.MetadataBuilder/applySqlFunction

Pero sigo obteniendo el mismo error exacto. No veo ninguna otra solución alternativa para hacer que funcione. Cualquier ayuda sería apreciada.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Solución para la base de datos en memoria H2 con consulta personalizada utilizando el dialecto de MySql

    Si estás escribiendo una prueba bajo una base de datos en memoria H2 que utiliza el dialecto de MySql (org.hibernate.dialect.MySQL5InnoDBDialect) y te encuentras con un error como “Function ‘convert_tz’ not found” al ejecutar una consulta personalizada con el bloque:

    DATE(CONVERT_TZ(NOW(),'GMT', (:timezoneOffset)))

    Existen algunas soluciones para este problema:

    Solución 1:

    Como se sugiere en esta publicación, puedes intentar lo siguiente:

    1. Agrega la siguiente dependencia a tu proyecto:
    <dependency>
        <groupid>com.h2database</groupid>
        <artifactid>h2</artifactid>
        <version>1.4.199</version>
        <scope>test</scope>
    </dependency>
    
    1. Utiliza un Dialect personalizado para la base de datos H2 en memoria, que mapee las funciones específicas de MySql a las funciones equivalentes de H2. Aquí tienes un ejemplo:
    public class CustomH2Dialect extends H2Dialect {
    
        public CustomH2Dialect() {
            super();
            registerFunction("convert_tz", new SQLFunctionTemplate(StandardBasicTypes.TIMESTAMP, "dateadd('hour', cast(substring(convert_tz(?1, 'UTC', ?2), 4, 3) as integer), dateadd('minute', cast(substring(convert_tz(?1, 'UTC', ?2), 7, 2) as integer), convert_tz(?1, 'UTC', ?2)))"));
        }
    }
    
    1. Utiliza el CustomH2Dialect para la configuración de tu base de datos H2 en memoria:
    spring.jpa.properties.hibernate.dialect = com.example.CustomH2Dialect
    

    Solución 2:

    También puedes intentar usar un SQLFunctionTemplate, como se muestra en este ejemplo:

    public class CustomDialect extends MySQL5InnoDBDialect {
    
        public CustomDialect() {
            super();
            registerFunction("convert_tz", new SQLFunctionTemplate(StandardBasicTypes.TIMESTAMP, "CONVERT_TZ(?1, ?2, ?3)"));
        }
    
    }
    

    Solución 3:

    Alternativamente, puedes intentar usar una función específica de H2, como CURRENT_TIMESTAMP(), en lugar de la función NOW() específica de MySql. Aquí tienes un ejemplo:

    @Query("SELECT DATE(CONVERT_TZ(CURRENT_TIMESTAMP(), 'GMT', :timezoneOffset)) FROM MyEntity")
    List<date> findByTimezoneOffset(@Param("timezoneOffset") String timezoneOffset);
    

    Esperemos que una de estas soluciones te ayude a resolver el problema.

Comments are closed.