Java连接Oracle数据库实战教程|驱动配置+代码实现+问题排查

Java连接Oracle数据库实战教程|驱动配置+代码实现+问题排查 一

文章目录CloseOpen

驱动配置与环境搭建:别让“翻译官”出问题

要说Java连Oracle,第一步就得搞定“驱动”——你可以把它理解成Java和Oracle之间的“翻译官”,两边说的“语言”不一样,没这个翻译官肯定聊不到一块儿去。但很多人栽就栽在这一步:要么下错了版本,要么配错了路径,结果翻译官要么“听不懂”,要么“没上班”。

先搞懂驱动版本:JDK和Oracle得“门当户对”

前两年我帮朋友公司排查一个老项目,他们用JDK 11连Oracle 19c,死活连不上,报错“Unsupported major.minor version 52.0”。后来一看,他们用的驱动还是ojdbc6(支持JDK 6),这就像让只会说文言文的翻译官去翻译英语,不报错才怪。其实Oracle的驱动版本和JDK版本是严格对应的,选错了根本跑不起来。

你可以参考下面这个表格,这是我根据Oracle官方文档整理的,不同JDK版本推荐用的驱动型号,记不住没关系,收藏起来照着选就行:

JDK版本 推荐Oracle驱动 支持的Oracle版本 下载地址(Oracle官网)
JDK 8 ojdbc8.jar 12c/18c/19c Oracle JDBC下载页
JDK 11/17 ojdbc11.jar 19c/21c Oracle JDBC下载页
JDK 7及以下 ojdbc6.jar/ojdbc5.jar 11g及以下 需从Oracle归档下载

小提醒

:如果你的项目用Maven管理依赖,直接在pom.xml里加坐标会更方便,不用手动下载jar包。比如JDK 8配ojdbc8,可以这样写:


com.oracle.database.jdbc

ojdbc8

21.1.0.0 <!-

  • 版本号可根据Oracle版本调整 >
  • 不过这里有个坑:Oracle的Maven仓库需要登录Oracle账号才能下载。我之前图省事没登录,结果Maven一直报“找不到依赖”,后来注册个账号配置进去才解决。如果你嫌麻烦,直接去官网下jar包,手动放进项目的lib目录也行,记得右键“Add as Library”,让IDE识别到这个驱动。

    环境变量这块,很多人容易忽略。尤其是Windows系统,如果你用命令行编译Java文件,得把驱动路径加到CLASSPATH里——就像告诉系统“翻译官”住在哪儿,不然系统找不到它。比如你的ojdbc8.jar放在D:libs目录,就把D:libsojdbc8.jar加到CLASSPATH变量里(多个路径用分号隔开)。不过现在IDE(比如IDEA、Eclipse)基本会自动处理这个,你只要确保驱动在项目依赖里,一般不用手动配环境变量,但命令行运行时还是得注意,我之前用cmd跑测试类就栽过这个跟头。

    代码实现与问题排查实战:从“能连上”到“连得稳”

    配好驱动,接下来就是写代码了。很多人觉得“不就是几行代码吗”,结果不是少写了关闭资源,就是没处理异常,上线后要么内存泄漏,要么一并发就崩。我之前接手过一个老项目,数据库连接用完从来不关,用户一多直接把数据库连接池占满,服务器天天报警,后来改成自动关闭才解决。下面我就带你从基础连接到优化,一步步把代码写扎实。

    基础连接代码:从“hello world”到规范写法

    先从最基础的JDBC连接开始,就像学编程先写“hello world”一样,能帮你理解底层逻辑。我把完整代码拆成几步,每步都标了注释,你跟着写就行:

    import java.sql.Connection;
    

    import java.sql.DriverManager;

    import java.sql.ResultSet;

    import java.sql.Statement;

    public class OracleJdbcTest {

    public static void main(String[] args) {

    //

  • 数据库连接信息:URL、用户名、密码
  • String url = "jdbc:oracle:thin:@localhost:1521:ORCLCDB"; // 注意URL格式

    String user = "scott"; // 你的Oracle用户名

    String password = "tiger"; // 你的Oracle密码

    //

  • 声明连接、语句、结果集对象(后面要关闭,所以定义在try外面)
  • Connection conn = null;

    Statement stmt = null;

    ResultSet rs = null;

    try {

    //

  • 加载驱动(JDK 6之后可省略,但 保留,兼容性更好)
  • Class.forName("oracle.jdbc.driver.OracleDriver");

    //

  • 获取数据库连接(核心步骤)
  • conn = DriverManager.getConnection(url, user, password);

    System.out.println("连接成功!数据库版本:" + conn.getMetaData().getDatabaseProductVersion());

    //

  • 执行SQL查询(示例:查EMP表的员工信息)
  • stmt = conn.createStatement();

    rs = stmt.executeQuery("SELECT EMPNO, ENAME FROM EMP WHERE DEPTNO = 30");

    //

  • 处理查询结果
  • while (rs.next()) {

    System.out.println("员工号:" + rs.getInt("EMPNO") + ",姓名:" + rs.getString("ENAME"));

    }

    } catch (Exception e) {

    e.printStackTrace(); // 实际项目中 用日志框架记录异常

    } finally {

    //

  • 关闭资源(必须按 rs -> stmt -> conn 的顺序关闭,避免内存泄漏)
  • try { if (rs != null) rs.close(); } catch (Exception e) {}

    try { if (stmt != null) stmt.close(); } catch (Exception e) {}

    try { if (conn != null) conn.close(); } catch (Exception e) {}

    }

    }

    }

    这里有几个关键点得注意:

  • URL格式jdbc:oracle:thin:@主机名:端口号:服务名。比如本地Oracle的默认端口是1521,服务名可能是ORCL(11g)或ORCLCDB(19c),你可以通过sqlplus / as sysdba登录后,执行select name from v$database;查服务名。我之前连同事的Oracle,他告诉我服务名是“ORCL”,我写上去一直连不上,后来发现他装的是19c,实际服务名是“ORCLCDB”,改完立马好了。
  • 资源关闭:必须在finally里关闭rs、stmt、conn,而且顺序不能乱。就像离开房间要先关灯、再关门,反过来就麻烦了。如果不关闭连接,数据库的连接数会被占满,其他程序就连不进来了——这就像你去餐厅吃饭,吃完占着桌子不走,别人只能干等着。
  • 异常处理:实际项目里别用e.printStackTrace(),用Log4j、SLF4J这类日志框架记录异常,方便排查问题。我之前调试时没打日志,出了错只知道连不上,不知道具体哪步错了,后来加了详细日志,才发现是密码输错了(尴尬)。
  • 连接池优化:让连接“复用”起来

    基础连接能跑通,但在实际项目中肯定不够用。比如一个Web项目,每秒有100个用户访问,每个请求都新建连接、用完关闭,数据库会被频繁的连接/断开操作拖垮。这时候就得用“连接池”——提前创建一批连接放在池子里,用户请求来时直接从池里拿,用完放回池里,不用每次都新建,效率能提升好几倍。

    我现在项目里常用阿里的Druid连接池,配置简单、功能还多(比如监控、防SQL注入)。下面是Druid连接池的配置和使用示例,你可以直接拿去改改参数用:

    import com.alibaba.druid.pool.DruidDataSource;
    

    import java.sql.Connection;

    import java.sql.ResultSet;

    import java.sql.Statement;

    public class DruidOracleTest {

    public static void main(String[] args) {

    //

  • 创建Druid数据源(连接池)
  • DruidDataSource dataSource = new DruidDataSource();

    //

  • 配置连接信息(和基础连接类似,但多了池相关参数)
  • dataSource.setUrl("jdbc:oracle:thin:@localhost:1521:ORCLCDB");

    dataSource.setUsername("scott");

    dataSource.setPassword("tiger");

    dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");

    //

  • 配置连接池参数(关键!根据项目并发量调整)
  • dataSource.setInitialSize(5); // 初始化连接数:刚启动时创建5个连接

    dataSource.setMaxActive(20); // 最大连接数:池里最多能放20个连接

    dataSource.setMinIdle(3); // 最小空闲连接数:没人用时至少保留3个连接

    dataSource.setMaxWait(60000); // 获取连接的超时时间:60秒拿不到就报错

    Connection conn = null;

    try {

    //

  • 从连接池获取连接(不用自己创建,直接拿现成的)
  • conn = dataSource.getConnection();

    System.out.println("从连接池获取连接成功!连接地址:" + conn);

    //

  • 执行SQL(和基础连接一样)
  • Statement stmt = conn.createStatement();

    ResultSet rs = stmt.executeQuery("SELECT COUNT() FROM EMP");

    if (rs.next()) {

    System.out.println("员工总数:" + rs.getInt(1));

    }

    } catch (Exception e) {

    e.printStackTrace();

    } finally {

    //

  • 归还连接到池里(不是关闭,而是放回池子给别人用)
  • if (conn != null) {

    try {

    conn.close(); // Druid重写了close方法,调用后连接会回到池里

    } catch (Exception e) {}

    }

    }

    }

    }

    用连接池时,参数配置很关键。我之前有个项目,初始连接数设了50,结果服务器一启动就占了数据库50个连接,其他服务连不上了。后来改成初始5个、最大20个,既保证了性能,又没影响其他服务。你可以根据项目并发量调整,比如日活低的系统,初始3-5个、最大10个就够了;高并发系统可以适当调大,但别超过数据库允许的最大连接数(Oracle默认一般是150,可以通过show parameter processes;查看)。

    常见错误排查:遇到问题别慌,按这几步来

    就算步骤都对,你可能还是会遇到各种报错。我整理了几个最常见的错误,附带上原因和解决办法,都是我踩过的坑,你照着排查准没错:

  • ClassNotFoundException:“找不到oracle.jdbc.driver.OracleDriver类”
  • 这八成是驱动没配好。先检查项目里有没有驱动jar包,或者Maven依赖是否正确引入。如果用IDEA,看看“External Libraries”里有没有ojdbc的jar包,没有的话重新加一下。我之前帮实习生排查时,发现他把jar包放在项目目录下,但没“Add as Library”,IDE根本没识别,加上就好了。

  • ORA-12514:“监听程序当前无法识别连接描述符中请求的服务”
  • 这个错90%是URL里的服务名写错了。你可以登录Oracle,执行select value from v$parameter where name='service_names';查正确的服务名。另外端口号也可能错,默认是1521,但如果安装时改过端口,就得用改后的端口(比如1522)。还有一种情况:Oracle监听没启动,在命令行执行lsnrctl start启动监听就行。

  • ORA-01017:“用户名/密码无效;登录被拒绝”
  • 密码输错了?或者用户名不对?先确认用户名密码是否正确(区分大小写!Oracle 12c之后密码默认区分大小写)。如果密码里有特殊字符(比如@、#),记得用双引号括起来。我之前密码里有个“$”,没加引号,一直提示无效,加上就好了。

  • 连接超时:“Could not get a connection, wait time out”
  • 这通常是连接池里的连接被用完了。可能是代码里没归还连接(比如忘了close()),或者并发太高连接不够用。你可以用Druid的监控页面(访问http://localhost:8080/druid)看看连接池状态,是不是“活跃连接数”等于“最大连接数”了。如果是前者,检查代码里的finally块有没有正确关闭连接;如果是后者,适当调大连接池的最大连接数。

    其实排查错误有个通用技巧:看报错信息的“Caused by”部分,那才是根本原因。很多人只看表面错误,忽略了根因,结果绕半天圈子。比如有次我遇到“连接超时”,表面看是连接池问题,实际“Caused by”是“ORA-00942: 表或视图不存在”——SQL写错了导致连接一直占着没释放,改了SQL就好了。

    你按这些步骤操作,Java连Oracle基本就稳了。记得代码里的连接信息(URL、用户名、密码)别硬编码,最好放配置文件里,方便上线后修改——我之前把密码写死在代码里,后来数据库密码改了,还得重新打包部署,别提多麻烦了。如果你按这些方法试了,或者有其他连Oracle的小技巧,欢迎在评论区告诉我,咱们一起避坑!


    其实设置连接池的初始连接数和最大连接数,就像给餐厅准备座位一样——座位太少,客人来了没地方坐;座位太多,空着也是浪费。你得先看看自己的项目平时多少人同时用,再决定准备多少“座位”。比如那种公司内部的后台管理系统,平时就几十个同事用,大家点来点去也不频繁,这种低并发场景,初始连接数设3-5个就够了,最大10个顶天了。我之前帮一个小团队搭系统,他们非说“多准备点保险”,初始连接数设了20,结果数据库天天报“连接数过多”,后来改成5个,运行半年都没出过问题,服务器资源还省了不少。

    要是你的项目用户多,比如电商网站或者教育平台,尤其搞活动的时候,可能一下子几百上千人同时访问,这时候就得把“座位”备足,但也不能瞎备。你得先搞清楚数据库本身能扛多少连接——Oracle默认一般能扛150个连接(可以用show parameter processes;查具体数),你设的最大连接数绝对不能超过这个数,不然数据库直接“罢工”,谁都连不上。我之前遇到个电商项目,促销时并发量冲到200,他们把最大连接数设了100,结果还是卡,后来发现初始连接数只设了10,用户一进来得等连接池慢慢创建新连接,改成初始20、最大80,页面加载速度快了一半。所以你看,日常并发量50左右的系统,初始5个、最大20个,既能应对突然多出来的用户,又不会让数据库“累着”,这才是合理的配置。


    如何确定JDK版本对应的Oracle驱动型号?

    可参考文章中Oracle驱动与JDK版本的对应关系:JDK 8推荐使用ojdbc8.jar(支持Oracle 12c/18c/19c),JDK 11/17推荐ojdbc11.jar(支持Oracle 19c/21c),JDK 7及以下需使用ojdbc6或ojdbc5.jar。若通过Maven管理依赖,可直接引入对应坐标,如JDK 8配置ojdbc8时,在pom.xml中添加com.oracle.database.jdbc:ojdbc8依赖(版本号根据Oracle数据库版本调整)。

    Oracle连接URL中的“服务名”如何查询?

    可通过SQLPlus登录数据库后执行查询命令获取服务名。具体步骤:使用sqlplus / as sysdba以管理员身份登录,然后执行select value from v$parameter where name=’service_names’;,查询结果即为当前数据库的服务名。URL格式需严格遵循jdbc:oracle:thin:@主机名:端口号:服务名,例如本地Oracle 19c的服务名若为ORCLCDB,URL可写为jdbc:oracle:thin:@localhost:1521:ORCLCDB。

    连接池的初始连接数和最大连接数该如何设置?

    需根据项目并发量调整:低并发场景(如日活较低的后台系统) 初始连接数3-5、最大连接数10;高并发场景可适当增加,但需注意不超过数据库允许的最大连接数(Oracle默认通常为150,可通过show parameter processes;查询数据库最大连接数)。例如日常并发量约50的系统,初始连接数设5、最大20即可,既能保证响应速度,又避免占用过多数据库资源。

    连接Oracle时提示“ClassNotFoundException”,可能的原因有哪些?

    该错误通常因驱动未正确引入导致。排查步骤:①检查项目依赖中是否包含Oracle驱动jar包(如ojdbc8.jar),Maven项目需确认pom.xml中是否配置正确依赖;②若手动添加jar包,需在IDE中右键“Add as Library”确保IDE识别;③命令行运行时,检查CLASSPATH环境变量是否包含驱动路径(如D:libsojdbc8.jar)。若依赖和路径均正确,可尝试重新构建项目或重启IDE。

    使用连接池后,连接用完需要手动关闭吗?

    需要。连接池的连接使用后需通过conn.close()归还到池内(而非真正关闭连接),否则连接会被永久占用,导致连接池耗尽。 在finally块中按“ResultSet→Statement→Connection”的顺序关闭资源,例如:在try-catch-finally结构中,finally块内依次关闭ResultSet、Statement,最后关闭Connection,确保资源正确释放,避免内存泄漏或连接数占满影响其他请求。

    0
    显示验证码
    没有账号?注册  忘记密码?