兼容mysql和oracle的数据库_Web项目--------原Oracle数据库的项目同时兼容MySql

本文介绍了如何使原Oracle数据库的项目同时兼容MySQL,主要涉及修改配置文件,使用DruidDataSource,以及在操作数据库时获取并传递当前数据库类型。详细讲述了通过继承SqlMapClientDaoSupportExtend类,并在方法中加入数据库类型参数来实现兼容性。还讨论了在SQL脚本中针对Oracle和MySQL的不同特性进行调整,如转换函数、字符串拼接、条件判断等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原Oracle数据库的项目同时兼容MySql步骤:

(一)修改资源配置文件applicationContext-dataSource.xml的数据库连接

19bfdf840ee87e0dd4cc2b76ebbf3c2c.png

e039061836308807ed99e9c4d04ba25a.png

Oracle数据库中加上from dual的原因:Oracle数据库中自带了一个虚拟表dual,这个的作用是测试数据库是否正常使用。

(二)添加一个类用于获取资源配置文件中当前使用的数据库类型以及该方法继承SqlMapClientDaoSupportExtend类,如果需要更多的方法,可以自行根据实际情况进行添加:

public class BaseDao extendsSqlMapClientDaoSupportExtend{

@AutowiredprivateDruidDataSource dataSource;publicObject queryForObject(String statementName){return this.queryForObject(statementName, newHashMap());

}/*** 查询时并携带当前连接池数据库类型作为参数

*@paramstatementName

*@paramparameterMap

*@return

*/

publicObject queryForObject(String statementName,Map parameterMap){

setDbType(parameterMap);returngetSqlMapClientTemplate().queryForObject(statementName, parameterMap);

}publicObject queryForObject(String statementName,Map parameterMap,Object resultObject){

setDbType(parameterMap);returngetSqlMapClientTemplate().queryForObject(statementName, parameterMap, resultObject);

}/*** 查询时并携带当前连接池数据库类型作为参数

*@paramstatementName

*@paramparameterMap

*@return

*/

publicList queryForList(String statementName){return this.queryForList(statementName, newHashMap());

}publicList queryForList(String statementName,Map parameterMap){

setDbType(parameterMap);returngetSqlMapClientTemplate().queryForList(statementName, parameterMap);

}public List queryForList(String statementName, int skipResults, intmaxResults){return this.queryForList(statementName, newHashMap(), skipResults, maxResults);

}publicList queryForList(final String statementName, final Map parameterMap, final int skipResults, final intmaxResults){

setDbType(parameterMap);returngetSqlMapClientTemplate().queryForList(statementName, parameterMap, skipResults, maxResults);

}publicMap queryForMap(final String statementName, final Map parameterMap, finalString keyProperty){

setDbType(parameterMap);returngetSqlMapClientTemplate().queryForMap(statementName, parameterMap, keyProperty);

}publicMap queryForMap(final String statementName, final Map parameterMap, final String keyProperty, finalString valueProperty){

setDbType(parameterMap);returngetSqlMapClientTemplate().queryForMap(statementName, parameterMap, keyProperty,valueProperty);

}public intupdate(String statementName){return update(statementName, newHashMap());

}public int update(final String statementName, finalMap parameterMap){

setDbType(parameterMap);returngetSqlMapClientTemplate().update(statementName, parameterMap);

}public int delete(String statementName) throwsDataAccessException {return delete(statementName, newHashMap());

}public int delete(final String statementName, finalMap parameterMap){

setDbType(parameterMap);returngetSqlMapClientTemplate().delete(statementName, parameterMap);

}/*** 获取数据库类型

*@paramparameterMap*/

private void setDbType(final MapparameterMap) {

String dataUrl=dataSource.getUrl();

dataUrl= dataUrl.substring(dataUrl.indexOf(":")+1);

dataUrl= dataUrl.substring(0,dataUrl.indexOf(":"));

parameterMap.put("dataBase", dataUrl);

}

}

详细说明:

(1)DruidDataSource类的自动装配

2894de75c387dbba1310b9e439c610fa.png

这个DruidDataSource类的来源就是要跟配置文件数据库连接池的名字一致,这个就是阿里巴巴开源的Druid连接池

dbb34ecd3be8eabc8e5b8554e3017b1f.png

(2)获取连接池里面的属性值url里面的字段,即截取出相应的数据库类型

a91136357594733255b9f88392a4b22d.png

执行过程分析:

String dataUrl = dataSource.getUrl();

获取到的值是:dataUrl="jdbc:oracle:thin:@192.168.0.153:1521:OANET"

dataUrl = dataUrl.substring(dataUrl.indexOf(":")+1);

获取到的值是:dataUrl=oracle:thin:@192.168.0.153:1521:OANET,dataUrl.indexOf(":")+1值就是5,即从下标5开始截取

dataUrl = dataUrl.substring(0,dataUrl.indexOf(":"));

获取到的值是:dataUrl=oracle,截取部分开始下标为0,结束下标为第一个冒号的下标,但不包括下标为第一个冒号的下标的那个标,左闭右开

(3)继承SqlMapClientDaoSupportExtend类,在每次写方法的时候获取当前的数据库的类型,例如:

a5491e5f84ed432669b6dc30d45e1cac.png

(4)如果正常来说,Sql脚本语言如果可以同时兼容MySql和Oracle的话就可以不用调用该类了,如果不能同时兼容的话就需要调用该类,其实该类的方法和SqlMapClientDaoSupportExtend类的区别就是传递多一个dataBase参数而已,这样当我们我们发现Sql脚本语言不能兼容同时兼容MySql和Oracle时,我们的类就需要先继承我们写的BaseDao类:

不能同时兼容,需先继承我们写好的BaseDao:

b2348eca78745881fc8794d9d220f707.png

同时可以兼容,直接继承SqlMapClientDaoSupportExtend类即可:

19c59db3969b90ae85f775c96d7161e7.png

(5)Sql脚本语言不能同时兼容MySql和Oracle的时,修改Sql的文件如下:

6709a063771f0354344eac2bdadc676f.png

(6)Sql脚本语言出现不兼容问题例子

第一步:修改该方法相应类的继承,改成继承BaseDao

4f5a94e304cc1a74eae7e6e0f66d428b.png

第二步:修改BaseDao里面的方法,由于BaseDao里面的queryForObject方法里不能传String参数过去,所以就用一个Map对象将String的值传过去

46c3a2a31b1684c991f46ef68ecb300d.png

未改前:

publicReserveInfoVO findOuternetReserveInfoByReserveSeq(String reserveSeq) {

Object obj= this.getSqlMapClientTemplate().queryForObject("outernetReserveInfo.findOuternetReserveInfoByReserveSeq", reserveSeq);if(obj != null && obj instanceofReserveInfoVO){return(ReserveInfoVO)obj;

}return null;

}

修改后:

publicReserveInfoVO findOuternetReserveInfoByReserveSeq(String reserveSeq) {

Map param=newHashMap();

param.put("reserveSeq", reserveSeq);

Object obj=queryForObject("outernetReserveInfo.findOuternetReserveInfoByReserveSeq", param);if(obj != null && obj instanceofReserveInfoVO){return(ReserveInfoVO)obj;

}return null;

}

第三步:修改完后,由于传递的参数由String变成了Map类型,所以Sql语句那边接收的参数要修改成Map,因为之前接受参数是用String的

6ae85a690e1155a95aa56a3dd8a6b982.png

Sql脚本语言兼容Oracle和MySql需要的注意点:

功能

Oracle

MySql

转换成字符串类型

TO_CHAR

DATE_FORMAT

转换成数值类型

TO_NUMBER

CAST

转换成日期类型

TO_DATE

STR_TO_DATE

字符拼接

||

CONCAT

判断字段是否为空,为空则返回0,反之返回本身

NVL

IFNULL

Desc做字段

C."DESC"

C.DESC

数据库合并行记录

WMSYS.WM_CONCAT

GROUP_CONCAT

条件判断

DECODE(NVL(1, 0), 0, 5, 1)

CASE IFNULL(1, 0) WHEN 0 THEN 5 ELSE 1 END

BLOB数据转换成字符串

UTL_RAW.CAST_TO_VARCHAR2

CAST

将字符串类型转换为blob类型

TO_BLOB

CAST

递归函数

START WITH......CONNECT BY

自定义函数再调用

通过表名获取表的主键

WHERE CU.CONSTRAINT_NAME = AU.CONSTRAINT_NAME

AND AU.CONSTRAINT_TYPE = 'P'

AND  AU.TABLE_NAME = #tableName#

WHERE table_name=#tableName#

AND COLUMN_KEY='PRI'

获取系统当前时间

SYSDATE

NOW()

获取一条数据

rownum

limit

删除表数据

delete(可用可不用表别名)

delete(不能用表别名)

1、To_char:转换成字符串类型

MySql中的date_format(date,'%Y-%m-%d')    -------------->oracle中的to_char();

例子1:获取当前系统时间

Mysql:SELECT DATE_FORMAT(NOW(),'%Y-%m-%d %H:%i:%S');

62cfd570cde91e8ace841e2d8b3006f7.png

Oracle: SELECT TO_CHAR(SYSDATE,'YYYY-MM-DD HH24:MI:SS') FROM DUAL

b1360c8720e1fa8b275d8968fd12d349.png

2、To_date:转换成日期类型

MySql中的str_to_date(date,'%Y-%m-%d')     -------------->oracle中的to_date();

例1:

Mysql:select str_to_date('2004-05-07 13:23:44','%Y-%m-%d %H:%i:%s')

5ca0192afa80f4b198b5206af278e835.png

Oracle:select to_date('2004-05-07 13:23:44','YYYY-MM-DD HH24:MI:SS') from dual

83b7720db99874c2aec7cb7eaffb5481.png

3、To_number:转换成数值类型如:To_number('1234.5'),结果:1234.5

例1:数字字符转换成整型:

MySql:CAST(a.sort AS SIGNED)

Oracle:to_number(a.sort)

4、字符拼接

MySql中concat('%','abc','%')------------------------>oracle中的'%' || 'abc' || '%'

例1:

MySql:CONCAT('%','不公示','%')

Oracle:'%'|| '不公示' ||'%'

5、判断字段是否为空,为空则返回0,反之返回本身:

MySql:select IFNULL('',0) from dual

Oracle:select nvl('',0) from dual

6、Desc做字段的区别:

desc字段---------------------->oracle中'desc'

MySql:

SELECT C.KEY, C.VALUE, C.DESC

FROMLZCITY_APPROVE_CONFIG CWHERE C.KEY ='SEQ_TYPE'

Oracle:

SELECT C.KEY, C.VALUE, C."DESC"FROMLZCITY_APPROVE_CONFIG CWHERE C.KEY = 'SEQ_TYPE'

7、数据库合并行记录

Oracle:WMSYS.WM_CONCAT(需要合并字段)

MySql:GROUP_CONCAT(需要合并字段)

8、条件判断:

Oracle:decode(nvl(1, 0), 0, 5, 1) from dual

MySql:case IFNULL(1, 0) when 0 then 5 else 1 end

原理:如果为1,则为0;如果为0,则为5;如果都不是则为1

9、BLOB数据转换成字符串(Oracle自带系统包utlraw将RAW转为VARCHAR2)

Oracle:UTL_RAW.CAST_TO_VARCHAR2(H.IMG_BODY)

MySql:CAST(H.IMG_BODY AS CHAR)

10、将字符串类型转换为blob类型

Oracle:to_blob(字段)

MySql:CAST(字段 AS BINARY)

11、递归函数例子,通过父节点找到所有的节点

因为MySql没有start with......connect by,所以要自己写一个自定义函数

MySql:

delimiter $$CREATE FUNCTION appr_index_tree_test(menu_root VARCHAR(200))RETURNS VARCHAR(1000)BEGIN

DECLARE sTemp VARCHAR(1000);DECLARE sTempChd VARCHAR(1000);SET sTemp='$';SET sTempChd=menu_root;WHILE sTempChd IS NOT NULLDOSET sTemp=CONCAT(sTemp,',',sTempChd);SELECT GROUP_CONCAT(seq_code) INTO sTempChd FROM appr_index_tree WHERE FIND_IN_SET(parent_seq_code,sTempChd)>0;END WHILE;RETURNsTemp;END$$

delimiter;

SELECT appr_index_tree_test(父节点)

Oracle:

start with seq_code=父节点

connectby prior seq_code = parent_seq_code

12、通过表名获取表的主键

MySql:

SELECT DISTINCT COLUMN_NAME FROMINFORMATION_SCHEMA.COLUMNSWHERE table_name=#tableName#AND COLUMN_KEY='PRI'

Oracle:

SELECT CU.COLUMN_NAME FROMUSER_CONS_COLUMNS CU, USER_CONSTRAINTS AUWHERE CU.CONSTRAINT_NAME =AU.CONSTRAINT_NAMEAND AU.CONSTRAINT_TYPE = 'P'

AND AU.TABLE_NAME = #tableName#

注意:其他相似例子

(1)往前一天:

Mysql:(Mysql则需要调用DATE_SUB函数,反之往后一天DATE_ADD)

select STR_TO_DATE(CONCAT(DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 1 DAY), '%Y-%m-%d'),' 00:00:01'),'%Y-%m-%d %H:%i:%s')

Oracle:(Oracle直接在当前系统时间减一,反之往后一天加一)

select TO_DATE(TO_CHAR((SYSDATE-1), 'YYYY-MM-DD') || ' 00:00:01','YYYY-MM-DD HH24:MI:SS') FROM dual

(2)往前一个月:

Mysql:select DATE_SUB(NOW(),INTERVAL 1 MONTH)

Oracle:select ADD_MONTHS(SYSDATE, -1) FROM dual

(3)上一个月最后一天:

Mysql:select LAST_DAY(DATE_SUB(NOW(),INTERVAL 1 MONTH))

Oracle:select LAST_DAY(ADD_MONTHS(SYSDATE, -1)) FROM dual

(4)上一个月最后一天再加一天:

Mysql:select DATE_ADD(LAST_DAY(DATE_SUB(NOW(),INTERVAL 1 MONTH)),INTERVAL 1 DAY)

Oracle:select LAST_DAY(ADD_MONTHS(SYSDATE, -1))+1 FROM dual

(5)MySql中,两个显示当天时间的区别:

(1)select CURDATE()

(2)select NOW()

结果:(1)2017-02-15

(2)2017-02-15 22:10:36

(13)获取查询结果的一条数据

MySql:

select * from temp where LIMIT 1

Oracle:

select * from temp where rownum=1

(14)删除表中的数据

MySql:

delete from temp where ...

Oracle:

delete from temp where ...

delete from temp p where ...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值