gpt4 book ai didi

java - Mysql SQL 查询 DATEDIFF 在模式为 MYSQL 的 H2 中失败

转载 作者:行者123 更新时间:2023-11-29 07:35:27 25 4
gpt4 key购买 nike

背景: 在我正在做的一个项目中 component testing在使用 JUnit 的 Spring Batch 上。这里的应用DB是MYSQL。在 Junit 测试执行中,我让数据源在

  • MySQL 和
  • H2(jdbc:h2:mem:MYTESTDB;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL)

基于配置。使用 MYSQL 作为数据源进行调试,使用 H2 在构建服务器中隔离运行测试。

一切正常,直到在应用程序逻辑中我不得不使用带 DATEDIFF 的查询。

问题:查询失败并显示

org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement

原因:即使通过H2 run on MySQL mode它使用 H2 函数,这些函数是不同的

MYSQL DATEDIFF definition is DATEDIFF(expr1,expr2)
e.g. SELECT DATEDIFF('2010-11-30 23:59:59','2010-12-31')
==> 1

H2 DATEDIFF definision is DATEDIFF(unitstring, expr1, expr2)
unitstring = { YEAR | YY | MONTH | MM | WEEK | DAY | DD | DAY_OF_YEAR
| DOY | HOUR | HH | MINUTE | MI | SECOND | SS | MILLISECOND | MS }
e.g. SELECT DATEDIFF(dd, '2010-11-30 23:59:59','2010-12-31')
==> 1

尝试过但失败的解决方案:我尝试编写自定义函数

 package com.asela.util;                                                                                                                                

import java.lang.reflect.Field;
import java.sql.Date;
import java.time.temporal.ChronoUnit;
import java.util.Map;
import java.util.Objects;

import org.h2.expression.Function;

public class H2Function {
public static long dateDifference(Date date1, Date date2) {
Objects.nonNull(date1);
Objects.nonNull(date2);
return ChronoUnit.DAYS.between(date1.toLocalDate(), date2.toLocalDate());
}
}

并用H2设置

DROP ALIAS IF EXISTS DATEDIFF;
CREATE ALIAS DATEDIFF FOR "com.asela.util.H2Function.dateDifference";

上面无法替换现有的 DATEDIFF 仍然失败

org.h2.jdbc.JdbcSQLException: Function alias "DATEDIFF" already exists; SQL statement:

我可以尝试使用其他任何方法来完成这项工作吗?

最佳答案

通过 Reflection 解决了这个问题。访问 H2 Functions 映射并从那里删除 DATEDIFF。然后添加替换功能。

package com.asela.util;

import java.lang.reflect.Field;
import java.sql.Date;
import java.time.temporal.ChronoUnit;
import java.util.Map;
import java.util.Objects;

import org.h2.expression.Function;

public class H2Function {

@SuppressWarnings("rawtypes")
public static int removeDateDifference() {
try {
Field field = Function.class.getDeclaredField("FUNCTIONS");
field.setAccessible(true);
((Map)field.get(null)).remove("DATEDIFF");
} catch (Exception e) {
throw new RuntimeException("failed to remove date-difference");
}
return 0;
}

public static long dateDifference(Date date1, Date date2) {
Objects.nonNull(date1);
Objects.nonNull(date2);
return ChronoUnit.DAYS.between(date1.toLocalDate(), date2.toLocalDate());
}
}

然后在模式中

CREATE ALIAS IF NOT EXISTS REMOVE_DATE_DIFF FOR "com.asela.util.H2Function.removeDateDifference";
CALL REMOVE_DATE_DIFF();
DROP ALIAS IF EXISTS DATEDIFF;
CREATE ALIAS DATEDIFF FOR "com.asela.util.H2Function.dateDifference";

关于java - Mysql SQL 查询 DATEDIFF 在模式为 MYSQL 的 H2 中失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49041723/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com