MyBatis连接Oracle数据库看似只需要改几行配置,实际开发中却经常因为驱动版本、URL写法、序列主键以及分页语法等问题导致启动报错或数据异常。尤其在Windows环境部署项目时,本地仓库路径、依赖解析方式以及驱动文件加载机制都与Linux存在差异,稍不注意就会卡在启动阶段。本文围绕这些容易忽略的配置细节展开说明,帮助开发者避开常见陷阱。

一、驱动依赖与本地仓库路径确认
MyBatis本身不包含Oracle JDBC驱动,必须在Maven或Gradle中单独引入。Oracle驱动版本需要与数据库版本匹配,Oracle 11g通常使用ojdbc6,Oracle 12c及以上建议使用ojdbc8或ojdbc10。以Maven项目为例,依赖坐标在不同版本中有明显变化,旧版groupId为com.oracle,新版为com.oracle.database.jdbc。如果写错groupId或版本号,构建阶段就会提示找不到对应jar包。在Windows环境下,Maven本地仓库路径通常为C:\Users\用户名\.m2\repository\com\oracle\ojdbc8\19.3.0.0,如果项目一直提示无法解析依赖,可以先检查该目录下是否存在ojdbc8-19.3.0.0.jar文件。注意路径中的反斜杠不要写成斜杠,例如C:\Users\admin\.m2\repository\com\oracle\ojdbc8\19.3.0.0才是正确写法。
下面是一个标准的Maven依赖示例:
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.3.0.0</version>
</dependency>
驱动类名的选择同样重要。Oracle提供两个常用驱动类:oracle.jdbc.driver.OracleDriver和oracle.jdbc.OracleDriver。前者是旧版注册方式,需要显式调用Class.forName才能加载;后者基于JDBC 4.0的SPI机制,驱动jar包放在classpath下即可自动注册。现在多数项目使用连接池或Spring Boot自动配置,建议配置为oracle.jdbc.OracleDriver,避免出现重复加载警告,也能减少手动注册代码。若使用Druid、HikariCP等连接池,driverClassName同样需要填写oracle.jdbc.OracleDriver。
二、连接URL与连接池参数设置
Oracle的JDBC连接URL有两种常见格式:服务名格式和SID格式。服务名格式为jdbc:oracle:thin:@//主机:端口/服务名,SID格式为jdbc:oracle:thin:@主机:端口:SID。Oracle 12c及更高版本多采用PDB模式,推荐使用服务名格式,例如jdbc:oracle:thin:@//192.168.1.100:1521/orclpdb。如果使用SID格式,@后面不要加双斜杠,直接写主机名和SID,例如jdbc:oracle:thin:@192.168.1.100:1521:orcl。混淆两种写法会导致ORA-12505或其他连接异常。
完整的mybatis-config.xml数据源配置示例如下:
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@//192.168.1.100:1521/orclpdb"/>
<property name="username" value="scott"/>
<property name="password" value="tiger"/>
<property name="poolMaximumActiveConnections" value="20"/>
<property name="poolMaximumIdleConnections" value="10"/>
</dataSource>
</environment>
</environments>
</configuration>
连接池参数需要结合实际并发量调整。MyBatis内置POOLED连接池的poolMaximumActiveConnections表示最大活跃连接数,poolMaximumIdleConnections表示最大空闲连接数。如果设置过小,高并发下会出现线程等待甚至超时;如果设置过大,可能超出Oracle数据库的进程数或会话数限制,触发ORA-00018或ORA-00020错误。生产环境更推荐使用Druid或HikariCP,它们提供更细粒度的连接检测和回收策略。对于Oracle,连接有效性检测语句应设置为select 1 from dual,而不是MySQL的select 1。同时注意数据库字符集与客户端一致,否则中文数据可能出现乱码。
三、主键返回与序列处理
Oracle没有像MySQL那样的自增主键,通常使用序列加触发器或者直接使用序列生成主键。MyBatis插入记录时若希望直接拿到主键值,需要使用selectKey元素。常见的写法如下:
<insert id="insertUser" parameterType="User">
<selectKey keyProperty="id" resultType="long" order="BEFORE">
select SEQ_USER_ID.nextval from dual
</selectKey>
insert into T_USER(ID, NAME, CREATE_TIME) values(#{id}, #{name}, sysdate)
</insert>
selectKey的order属性决定取值时机。BEFORE表示先查询序列值再执行插入,这样实体类中的id字段会在插入前被赋值,应用代码可以立即使用。AFTER表示先插入再取主键,通常用于数据库自动生成主键或触发器场景。如果主键由触发器生成,MyBatis插入后无法直接获取主键值,需要额外查询,因此更推荐使用显式序列加BEFORE方式。keyProperty必须与实体类字段名一致,resultType要与序列返回值类型匹配,例如number(19)对应long。序列没有权限时会报ORA-02289错误,需要确认当前用户是否拥有序列权限,跨schema时要在序列名前面加上schema,例如select SCOTT.SEQ_USER_ID.nextval from dual。另外selectKey中的SQL语句不要以分号结尾,Oracle JDBC驱动对末尾分号比较敏感。
批量插入时如果需要返回每个记录的主键,selectKey无法直接作用于foreach循环内的每一条记录。常见做法是先一次性取出多个序列值,再传递给插入语句。例如可以通过下面的方式批量获取序列:
select SEQ_USER_ID.nextval from dual connect by level <= 10
然后在Java代码中把取到的序列值分配给待插入的对象,最后执行批量插入。这样可以避免逐条执行selectKey带来的性能开销,也保证主键的连续性和可控性。
四、分页与特殊SQL写法
Oracle 12c以下版本没有limit offset语法,只能通过ROWNUM实现分页。一个典型的错误写法是直接在where条件中使用ROWNUM,例如select * from T_USER where ROWNUM > 10 and ROWNUM <= 20。这种写法永远查不到数据,因为ROWNUM是Oracle在结果集输出时动态编号的伪列,先有条件过滤再生成行号,所以第一行的ROWNUM为1,不可能满足大于10的条件。正确做法是使用嵌套子查询:
select * from (
select t.*, rownum rn from (
select * from T_USER order by ID
) t where rownum <= 20
) where rn > 10
内层先按业务需求排序,中间层限制最大行号并给ROWNUM起别名,最外层再过滤起始行号。这种写法兼容Oracle 8i到11g。Oracle 12c及以上版本推荐使用OFFSET FETCH NEXT语法,性能更好且可读性更高。如果项目使用PageHelper分页插件,可以通过配置helperDialect为oracle12c来让插件生成新语法,提升分页效率。
其他容易忽略的Oracle特殊性还包括:Oracle中空字符串与NULL等价,MyBatis的if test条件判断时需要注意查出的空字符串字段可能被当作NULL处理;日期过滤应使用to_date函数显式转换,例如to_date(#{startDate}, 'yyyy-mm-dd hh24:mi:ss'),避免隐式转换导致索引失效;模糊查询多个条件拼接应使用||连接符,而不是CONCAT函数,因为CONCAT只支持两个参数。掌握这些细节可以让MyBatis与Oracle的配合更加稳定,减少线上环境出现SQL异常的概率。
MyBatis连接OracleOracle JDBC驱动数据库连接配置修改时间:2026-08-26 22:09:59