如何用单个Liquibase <insert>标签兼容Oracle与HSQLDB布尔值插入
跨数据库适配单
<insert>标签插入布尔值需求 我需要用单个<insert>标签同时在生产环境的Oracle和测试环境的HSQLDB中插入新行,但布尔值存在兼容问题——Oracle要求值为1,HSQLDB要求值为true。目前我通过两个带dbms属性的<insert>标签实现,请问能否移除dbms属性,用同一个<insert>标签完成跨数据库适配?
当前实现代码:
<insert dbms="oracle" tableName="MY_TABLE"> <column name="ID" valueComputed="MY_TABLE_ID_SEQ.NEXTVAL"/> <column name="NAME" value="JOHN DOE"/> <column name="VISIBLE" value="1"/> </insert> <insert dbms="hsqldb" tableName="MY_TABLE"> <column name="ID" valueComputed="MY_TABLE_ID_SEQ.NEXTVAL"/> <column name="NAME" value="JOHN DOE"/> <column name="VISIBLE" value="true"/> </insert>
解决方案
可以通过以下几种方式实现单标签跨库适配:
方式1:利用数据库内置变量做条件判断
如果用的是Liquibase这类数据库迁移工具,直接用内置的database.type变量做动态判断:
<insert tableName="MY_TABLE"> <column name="ID" valueComputed="MY_TABLE_ID_SEQ.NEXTVAL"/> <column name="NAME" value="JOHN DOE"/> <column name="VISIBLE" value="${database.type == 'ORACLE' ? '1' : 'true'}"/> </insert>
如果是MyBatis环境,可通过数据库ID参数做判断:
<insert tableName="MY_TABLE"> <column name="ID" valueComputed="MY_TABLE_ID_SEQ.NEXTVAL"/> <column name="NAME" value="JOHN DOE"/> <column name="VISIBLE" value="${@org.apache.ibatis.session.Configuration@getDatabaseId() == 'oracle' ? '1' : 'true'}"/> </insert>
方式2:自定义类型处理器
编写一个跨数据库布尔值转换的类型处理器,根据当前连接的数据库类型自动适配值:
- 实现类型处理器类,核心逻辑是在设置参数时判断数据库类型,Oracle传
1,HSQLDB传true - 在
<column>标签中指定该处理器:
<insert tableName="MY_TABLE"> <column name="ID" valueComputed="MY_TABLE_ID_SEQ.NEXTVAL"/> <column name="NAME" value="JOHN DOE"/> <column name="VISIBLE" value="true" typeHandler="com.yourpackage.CrossDbBooleanTypeHandler"/> </insert>
方式3:用SQL表达式兼容转换
通过SQL的CASE表达式动态生成对应值,无需依赖框架特性:
<insert tableName="MY_TABLE"> <column name="ID" valueComputed="MY_TABLE_ID_SEQ.NEXTVAL"/> <column name="NAME" value="JOHN DOE"/> <column name="VISIBLE" valueComputed="CASE WHEN SYS_CONTEXT('USERENV','DB_NAME') = 'ORCL' THEN 1 ELSE TRUE END"/> </insert>
注:Oracle的SYS_CONTEXT('USERENV','DB_NAME')可替换成对应数据库的环境判断语句,HSQLDB可通过DB_NAME()函数获取库名。
内容的提问来源于stack exchange,提问作者stefan.stt
相关产品推荐
相关产品推荐

