使用MyBatis、H2和Oracle程序进行java集成测试
我有一个存储Oracle过程,我这样调用它:
CALL MY_PROC(
p_arg => #{arg, jdbcType=INTEGER, mode=IN},
p_var => #{var, jdbcType=VARCHAR, mode=IN},
p_date => #{date, jdbcType=DATE, mode=IN}
)
我用MyBatis
这样写:
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.MyMapper">
<update id="callMyProc" statementType="CALLABLE">
CALL MY_PROC(
p_arg => #{arg, jdbcType=INTEGER, mode=IN},
p_var => #{var, jdbcType=VARCHAR, mode=IN},
p_date => #{date, jdbcType=DATE, mode=IN}
)
</update>
</mapper>
过程本身会执行一些FOR UPDATE
,因为我必须在更新行之前锁定它们。代码完成了它的工作,但我现在想编写一些集成测试,我使用H2作为数据库。我知道在这种情况下,我应该编写用户定义的函数来处理这种情况。我非常确定,编写这样一个查询(为了这个问题,sql查询被简化了):
CREATE ALIAS IF NOT EXISTS MY_PROC AS $$
import java.net.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.UUID;
import java.time.LocalDateTime;
@CODE
void callMyProc(Connection conn, Integer p_arg, String p_var, LocalDateTime p_date) throws Exception {
String sqlStatement = String.format("UPDATE mytable SET myvar = '%s', mydate = '%t' WHERE myarg = %d", p_var, p_date, p_arg);
PreparedStatement ps = conn.prepareStatement(sqlStatement);
ps.execute();
}
$$;
可以做到这一点,但不幸的是,由于MyBatis格式,我遇到了语法错误:
### The error may exist in com.example/MyMapper.xml
### The error may involve com.example.MyMapper.callMyProc
### The error occurred while executing an update
### SQL: CALL MY_PROC( p_arg => ?, p_var => ?, p_date => ? )
### Cause: org.h2.jdbc.JdbcSQLSyntaxErrorException: Błąd składniowy w wyrażeniu SQL "CALL MY_PROC(
P_ARG[*] => ?,
P_VAR[*] => ?,
P_DATE[*] => ?
)"
Syntax error in SQL statement "CALL MY_PROC(
P_ARG[*] => ?,
P_VAR[*] => ?,
P_DATE[*] => ?
CALL MY_PROC(
p_arg => ?,
p_var[*] => ?,
p_date[*] => ?
) [42000-200]
我的问题是,我应该如何为程序编写我的H2别名,以便MyBatis和H2都能满足要求
# 1 楼答案
正如用户所建议的,事实证明,去掉Oracles语法,只需将MyBatis mapper写成这样就足够了:
我还必须将
date
类型更改为TIMESTAMP
,别名应该如下所示:匹配
LocalDateTime
类型的Java(此时,从LocalDateTime
到java.util.Date
的映射将自动完成)。这样编写的唯一缺点是,在调用存储过程时,必须注意参数的顺序