MyBatis调用Oracle自定义函数遇ORA-00904错误的解决咨询
解决MyBatis调用Oracle带命名空间函数的ORA-00904错误
问题背景
存在Oracle包函数secureUser.collection.getExampleId,该函数可根据传入的keyId返回Example Id。在PL/SQL中直接执行调用该函数的SQL语句可正常返回结果,但在MyBatis Mapper中调用时触发ORA-00904错误,提示"SECUREUSER"."COLLECTION"."GETEXAMPLEID": 无效标识符,推测是MyBatis自动给函数名添加引号导致解析错误。
解决方案
方法1:使用CDATA块包裹函数调用
MyBatis解析SQL时会对包含特殊字符(如点号)的内容进行错误转义,使用CDATA块可以让函数调用部分直接原样传递给Oracle执行,避免MyBatis的自动引号添加。修改后的Mapper代码如下:
<mapper namespace="core.namespace.dao.mybatis.MyMapper"> <resultMap id="Data" type="core.model.impl.table"> <result column="column1" property="one" /> <result column="column2" property="two" /> <result column="column3" property="three" /> <result column="secure" property="sec" /> </resultMap> <select id="getSecure" parameterType="java.lang.Long" resultMap="Data"> select column1, column2, column3, <![CDATA[ secureUser.collection.getExampleId(#{id}) ]]> secure from mytable mt where mt.keyId = #{id} </select> </mapper>
方法2:严格匹配对象大小写(若对象创建时使用双引号)
如果Oracle中的包和函数是通过双引号指定大小写创建的(如CREATE PACKAGE "secureUser"."collection"),则调用时必须用双引号包裹每个命名空间部分,确保Oracle能识别正确的对象:
<select id="getSecure" parameterType="java.lang.Long" resultMap="Data"> select column1, column2, column3, "secureUser"."collection"."getExampleId"(#{id}) secure from mytable mt where mt.keyId = #{id} </select>
原理说明
MyBatis默认会对SQL中的标识符进行解析,当遇到包含点号的内容时,可能误将其识别为表-列结构并自动添加引号,导致Oracle无法识别包函数的完整路径。CDATA块会屏蔽MyBatis的解析逻辑,让函数调用语句原封不动发送到数据库执行;而严格匹配大小写则是保证Oracle能找到正确的大小写敏感对象。
内容的提问来源于stack exchange,提问作者David Hash
相关产品推荐
相关产品推荐

