资讯动态

Eclipse连接Oracle数据库全指南:JDBC驱动搭配、连接串与ORA报错排查

发布时间:2026/10/21 7:51:55 来源:尧图企业网站定制
1. 版本组合决定成败Eclipse、JDK、Oracle驱动怎么搭配我第一次在Eclipse里头连Oracle是在一个用惯了MySQL的项目里突然被要求切库。本以为改个连接串就行结果从下载驱动到跑出第一条select语句整整折腾了一个多小时。后来回头看问题基本都出在版本匹配上——Oracle不像MySQL那样随便拿个jar就能糙着用版本不对报错的方式千奇百怪绝对让你摸不着头脑。所以这篇东西我不打算只贴一段代码让你复制。我想把你可能遇到的环境坑、连接串参数、增删改查写法、以及我最常被问的各种ORA报错从头到尾梳理一遍。适合谁看第一次在Eclipse里接Oracle或者接上了但总在报错边缘试探的人。已经写过几年Java的老手也可以直接跳到报错排查那一节说不定能找到点新思路。1.1 Java版本和Oracle版本的隐藏默契先说最容易被忽略的一点JDK版本、数据库版本、驱动jar版本三者之间存在严格的对应关系。Oracle官方给驱动包的命名逻辑其实很直白。你下载到的ojdbc8.jar对应JDK 8ojdbc11.jar对应JDK 11。如果我的电脑是JDK 17却拿着ojdbc8.jar去连Oracle 19c通常也能跑通但偶尔会给你抛出一些莫名其妙的兼容性警告。反过来说JDK 8环境硬上ojdbc11.jar大概率直接给你报UnsupportedClassVersionError——这个错误翻译过来就是你编译驱动的JDK比我当前环境的JDK新我跑不了。这个问题在Eclipse里尤其隐蔽因为Eclipse自带编译级别设置就算你用JDK 17跑项目如果Project facet或者Compiler compliance level设成了1.8还是会出问题而且控制台报错信息经常被Eclipse吞掉一大半排查体验相当痛苦。我的建议是别去挑战未知的极限直接用最常见的组合JDK 8搭配ojdbc8.jar连Oracle 11g、12c都毫无压力如果数据库是Oracle 19c以上用JDK 11或者JDK 17对应上ojdbc11.jar。至于Oracle 21c那批新版本老实说很多公司还没升级遇到了再单独处理。1.2 驱动jar下载与导入Eclipse的过程驱动jar去哪找很多新手习惯去Maven中央仓库直接搜ojdbc这没问题但有一个细节得注意Oracle官方从18c开始ojdbc的Maven坐标有些调整如果你用的是老版本Oracle数据库最好去Oracle官方下载页找对应版本的jar。下载完之后文件是一个jar包里面是没有源码的里面有几个关键类oracle.jdbc.OracleDriver就是入口你所有连接的第一步就是从加载它开始的。把jar导入Eclipse有两种做法。一种是把jar丢到项目的WebContent/WEB-INF/lib目录下然后右键项目选Build Path - Add to Build Path这适合动态Web项目。另一种是直接在项目上右键Build Path - Configure Build Path在Libraries标签页里点Add External JARs选中你下载的ojdbc包。无论哪种方法导入之后我强烈建议你展开Referenced Libraries看一眼确认jar被识别了而不是变成灰色状态。很多人就是在这一步稀里糊涂地把jar加了一半结果运行时报ClassNotFoundException还以为是连接串写错了。还有个更容易踩的坑如果你的项目是Maven工程在pom.xml里声明了ojdbc依赖同时又手动往Build Path里加了同一个jar运行时可能会因为两个类源冲突导致奇怪的报错。Maven项目就老老实实依赖管理非Maven项目就手动导入别混着来。2. JDBC连接串拆解thin驱动里那串URL到底写什么连接串就是JDBC的入场券。Oracle的JDBC URL不像MySQL那么单一它至少有三种写法SID方式、Service Name方式、以及更老的DESCRIPTION方式。很多报错根本原因不是密码错而是URL写法跟数据库的真实服务名对不上。2.1 SID和Service Name一字之差决定生死我见过最多的一种报错长这样ORA-12505: TNS:listener does not currently know of SID given in connect descriptor这个报错说得很明白监听器不认识你给的SID。多数情况下不是你密码错了而是你把SID和服务名搞混了。Oracle的连接串有两种核心写法我统计过大概长下面这个表格这样连接方式URL写法典型报错SID方式适合老数据库jdbc:oracle:thin:192.168.1.100:1521:orclORA-12505SID写错Service Name方式12c后常用jdbc:oracle:thin://192.168.1.100:1521/orclORA-12514服务名写错注意看写法上的区别SID方式在端口后面跟冒号写的是数据库实例名Service Name方式在端口后面跟斜杠写的是数据库服务名。两者大多数情况下值一样但性质完全不同。Oracle 12c以后数据库默认用Service Name注册到监听器你再用冒号方式去连反而容易碰壁。Windows上如果装了Oracle客户端可以用lsnrctl status命令查看监听器到底注册了什么在命令行里输入这个命令看输出里的“Services”行里面列出的名字就是Service Name。我在无数个别人报错的环境里最后都是靠这一招救回来的。2.2 用户名、密码和连接串里的隐藏坑Oracle默认安装后有超级管理员账号system密码安装时自己设置普通业务账号一般要DBA用create user命令建出来。如果你在Eclipse里第一次写测试类拿system账号直接连确实可以跑通但这会在后续测试时给你的操作权限埋雷——system用户的权限过大增删改查没问题但如果你误写一句drop table系统不会拦你。我建议在建表测试之前用管理员账号建一个普通用户再赋予权限这样做一方面安全另一方面也更贴近真实生产环境的配置方式。还有一个小细节很容易被忽略连接串里不要裸写密码。测试阶段无所谓但一旦代码要在多个环境之间切换密码写死在代码里就是一场灾难。我后来习惯把连接串、用户名、密码统一放到properties配置文件里Eclipse下新建一个db.properties文件再把文件放到src目录代码里用ResourceBundle或者Properties读取。这样换环境的时候只需要改配置不用动代码。做法很简单但收益很大下文的方法章节里我会给出具体的封装代码。2.3 测通连接最快的方式Eclipse里直接跑一段验证代码配置好了驱动和连接串第一件事不是写增删改查而是先写一个三行代码的验证类专门用来确认连接能被成功创建。真正的连接代码一共三步加载驱动类、用DriverManager拿Connection、判断连接不为空。很多老手喜欢把这三步直接写在main方法里测我也一样。import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class ConnectionTest { public static void main(String[] args) { String url jdbc:oracle:thin://192.168.1.100:1521/orcl; String user scott; String password tiger; try { Class.forName(oracle.jdbc.OracleDriver); Connection conn DriverManager.getConnection(url, user, password); System.out.println(连接成功 conn); } catch (ClassNotFoundException e) { System.out.println(找不到驱动类检查jar是否导入); e.printStackTrace(); } catch (SQLException e) { System.out.println(连接失败错误代码 e.getErrorCode()); e.printStackTrace(); } } }如果控制台打印出类似Oracle JDBC driver的类信息恭喜你连接链路已经完全畅通后面就是纯粹的业务代码问题。如果这里就卡住先别急着往下走直接跳到第5节看排查路径。3. 三个基础对象的练习Statement、ResultSet和动手写第一条查询一旦连接打通接下来就是CRUD。但在铺开四个操作之前我觉得有必要先把JDBC里三个核心对象讲透——Statement、PreparedStatement、ResultSet。这三个东西是执行SQL的载体也是新手最容易产生困惑的地方。3.1 Statement和PreparedStatement的真正区别我早年在网上看代码有人说PreparedStatement性能更好有人说Statement够用。实际上PreparedStatement最大的优势不是性能而是安全。Statement是把用户输入直接拼接到SQL字符串里如果输入的内容里包含单引号比如用户输入了“1‘ or 1’1”拼出来的SQL就会变成一段危险的查询条件分分钟把你的数据全查出来。PreparedStatement用问号占位符代替真实的输入值执行时参数会被当作纯数据处理再也不会参与SQL语法解析这就在原理上绝了SQL注入的路子。举个直观的例子。假设你要按用户名查用户用Statement写String sql SELECT * FROM t_user WHERE user_name name ;如果name的值是admin OR 11那实际执行的SQL就变成了SELECT * FROM t_user WHERE user_name admin OR 11条件恒为真整个表的数据全都出来了。这种攻击在JDBC里就是拼字符串拼出来的。用PreparedStatement之后代码变成PreparedStatement ps conn.prepareStatement(SELECT * FROM t_user WHERE user_name ?); ps.setString(1, name);即使name里带着单引号和OR条件Oracle也只会把它当作一个普通的字符串参数去匹配字段不会当成SQL逻辑去执行。就凭这一点我强烈建议你从第一行查询就开始用PreparedStatement不要给自己留下换用Statement的机会。3.2 ResultSet的正确遍历方式别再用while错位遍历拿到查询结果之后核心操作就是遍历ResultSet。新手最常见的错误是在第一次调用rs.next()之前就直接getString导致拿不到数据。实际上ResultSet就像一根指针初始位置指向第一条记录之前必须先调用next()把指针移到第一条记录上才能取数据每次调用next()都会判断下一行是否存在返回true就继续移动指针返回false就结束循环。所以标准写法永远是while (rs.next())在循环体里通过rs.getXxx方法拿列值。这里有个进阶建议取列值的时候优先按列名取不要按列下标取。下标方式写起来短但在修改SQL、增减字段时很容易错位——SQL里多查了一个字段下标就全乱了程序不报错数据却全错。更麻烦的是这种错位很难定位因为你看到的是能跑的值不是报错信息。我见过很多同事调试到怀疑人生最后发现只是下标序号对错了列。用列名的方式例如rs.getString(user_name)哪怕SQL改了字段顺序代码依然稳。代价就是多打几个字这点成本相当划算。3.3 一个可复用的executeQuery模板我把查询这块的套路稳定下来之后每次写DAO层都感觉很省心。骨架长这样public ListMapString, Object findUsersByName(String name) { String sql SELECT user_id, user_name, email, create_time FROM t_user WHERE user_name LIKE ?; ListMapString, Object list new ArrayList(); try (Connection conn DriverManager.getConnection(URL, USER, PASSWORD); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, % name %); try (ResultSet rs ps.executeQuery()) { while (rs.next()) { MapString, Object row new HashMap(); row.put(userId, rs.getLong(user_id)); row.put(userName, rs.getString(user_name)); row.put(email, rs.getString(email)); row.put(createTime, rs.getTimestamp(create_time)); list.add(row); } } } catch (SQLException e) { e.printStackTrace(); } return list; }这段代码用了try-with-resources语法连接、语句、结果集都能自动关闭省去了一堆finally里的空判断。这是JDK 7以后就有的语法如果你还在JDK 6那就只能老老实实写finally手动关资源了。下一节我会展示完整的手动关闭版和自动关闭版的对比让没有接触过这个特性的新手也知道怎么回事。4. 增删改查完整落地预编译、事务边界和主键生成策略连接打通查询也能跑了剩下的增删改就是体力活了。不过体力和体力也有区别——如果你不处理主键生成策略、不关心事务边界代码虽然能跑但一旦数据量上来各种奇怪的问题就都来了。4.1 建一张测试表Oracle的主键生成与MySQL完全不同如果你的数据库是Oracle 12c以前的老版本建表语句里不能像MySQL那样写AUTO_INCREMENT这可能是Oracle劝退新手的最大一个坎。Oracle传统的主键生成方式是用序列Sequence再加一个触发器在插入前自动填充主键值。CREATE TABLE t_user ( user_id NUMBER(10) PRIMARY KEY, user_name VARCHAR2(50) NOT NULL, pass_word VARCHAR2(100), email VARCHAR2(100), create_time DATE DEFAULT SYSDATE ); CREATE SEQUENCE seq_user_id START WITH 1 INCREMENT BY 1 NOMAXVALUE;然后在插入语句里直接引用序列的nextvalString insertSql INSERT INTO t_user(user_id, user_name, pass_word, email, create_time) VALUES(seq_user_id.NEXTVAL, ?, ?, ?, SYSDATE);如果数据库是Oracle 12c及以上其实有更省事的写法直接在字段上写GENERATED BY DEFAULT AS IDENTITY就可以实现自增。但你得先确认你的Oracle版本支持这个特性否则建表就会报错。老项目的Oracle版本往往比想象中低尤其很多还是11g稳一点还是用序列加触发器兼容性最好。4.2 增插入语句的返回值和executeUpdate的区别有了表结构之后增删改其实共用同一套executeUpdate方法区别只在SQL内容不同。executeUpdate返回一个int值表示受影响的行数。插入成功时这个值通常是1。很多人不太重视这个返回值但我建议你拿它来做操作结果判断返回值大于0说明SQL真的影响了数据返回0说明SQL执行了但没有数据变更要么是条件不匹配要么是数据已经存在被过滤掉了。插入代码有一个重要选项需要注意是否要回传自增主键的值。如果你的业务代码在插入之后马上需要拿到新的主键ID比如创建订单后立刻查询订单详情就不能只执行一条executeUpdate就完事。Oracle下通常会把序列的nextval单独查出来先放到一个变量里再用这个变量插入这是一种方式另一种是把主键生成过程写在Oracle的存储过程里用CallableStatement处理。我个人更推荐前者代码更直观也更容易调试。4.3 改和删条件参数别写死注意影响行数更新和删除的代码模式和插入高度一致唯一的重点是WHERE条件要设计稳妥。用PreparedStatement的动态?占位符填写条件避免条件拼接时把单引号问题留给字符串。写条件时还要留心如果条件字段是可空的就一定要考虑NULL参与比较的情况。Oracle里NULL不能直接用等号或不等号判断必须用IS NULL或IS NOT NULL。还有一个细节跟我开头提到的资源关闭有关PreparedStatement执行完之后不仅ResultSet要关闭Statement也要关闭。Connection最好更是用完之后立刻归还或关闭。很多老项目跑一段时间就报“连接数过多”很可能不是数据库服务器设置有问题而是应用代码的Connection没有被正常关闭把数据库连接池里的连接耗尽Oracle侧的表现就是经典的ORA-12519提示数据库实例无法提供更多连接。这个错有一半以上是应用没关连接造成的。4.4 批处理和手动事务写法不难但对大数据量必须这么做往表里一次性插入几万条数据时逐条执行executeUpdate会慢到你想砸电脑。正确姿势是用Batch批处理先把SQL加入批处理队列攒够一批再一起发送给Oracle减少网络往返。Connection conn null; PreparedStatement ps null; try { conn DriverManager.getConnection(URL, USER, PASSWORD); conn.setAutoCommit(false); // 关闭自动提交让多条插入变成一个事务 String sql INSERT INTO t_user(user_id, user_name, email) VALUES(seq_user_id.NEXTVAL, ?, ?); ps conn.prepareStatement(sql); for (int i 0; i 10000; i) { ps.setString(1, user_ i); ps.setString(2, user i example.com); ps.addBatch(); if (i % 500 0) { ps.executeBatch(); } } ps.executeBatch(); conn.commit(); } catch (SQLException e) { if (conn ! null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } e.printStackTrace(); } finally { // 手动关闭 ps 和 conn }批处理的关键是分段提交不要一次性addBatch一万条才执行尽量每500条提交一次既减少网络交互又不至于把内存占用搞得过大。事务这块核心逻辑是把setAutoCommit(false)放在最前面所有执行完毕后再commit任何一步出错都rollback回滚。我把这段代码放在这里展示就是想让你注意到一个细节批处理启动之前先别急着写数据先设计好事务边界。5. 排障实战ORA报错从哪查起Eclipse控制台怎么读这部分是全文的重头戏。因为我发现很多人的问题不是不会写代码而是不会根据报错信息做判断。我整理了在Eclipse里接Oracle时最常碰到的几类问题你如果遇到了按顺序排查大概率能在十分钟内找到原因。5.1 ClassNotFoundException / No suitable driverEclipse控制台里如果打印ClassNotFoundException: oracle.jdbc.OracleDriver这个问题百分百是驱动没加载进来不是代码问题。排查顺序是先看Referenced Libraries里有没有ojdbc的jar再看jar包大小是否正常一个几十KB的jar基本是下载出错最后确认项目Clean之后再重新编译运行。如果你是用Tomcat跑Web项目还得确认jar是否同时存在于Tomcat的lib目录和项目的WEB-INF/lib目录否则运行时会因为类加载机制不同产生诡异问题。另一种情况是抛sqlException: No suitable driver说明DriverManager无法识别你的URL。原因通常是Class.forName那行根本没执行到或者URL格式写错了。有一个快速验证方法把Class.forName那一行临时注释掉看还是否能连上。JDBC 4.0之后支持驱动自动加载如果配置正常即使不调用Class.forName也能连接。如果你关了自动加载注释反而连不上说明类路径里根本没有驱动实现类。5.2 ORA-12505与ORA-12514连接串监听器相关的区分这两个错误我前面提过本质上都是监听器找不到目标但细节不同。ORA-12505的关键词是SID报错说它不知道你给的SID。这时你要去确认连接串里的SID是不是数据库真实的实例名。Windows下的检查命令是lsnrctl status但是注意如果你的项目是连接远程Linux服务器上的Oracle就要在服务器上执行这条命令来看监听器注册的信息。ORA-12514的关键词是service name报错说监听器不认识你给的服务名。这时候先看数据库的service_names参数再检查URL里的斜杠后面写的名字是否一致。我遇到过一种情况但是服务名后面还带了域名后缀比如orcl.yourcompany.com真实服务名跟简写不一样URL里直接写orcl就会12614。遇到这两个错最快的方式是把SQLPlus连接方式拿来对照。如果你能在命令行用sqlplus user/pass//host:port/servicename连上数据库那就说明URL的host、port、服务名全对问题出在Java代码或者网络层面如果SQLPlus也连不上直接说明监听器或数据库本身有问题跟你的Java代码没任何关系。这个对照法能迅速帮你划清问题的边界。5.3 ORA-01017和ORA-28000账号层面的两个高频坑ORA-01017表示用户名密码错误或者用户名不存在这是最老实的报错没有歧义。排查时我看三个地方用户名是否区分大小写Oracle默认把不带引号的标识符转成大写如果你建用户时用了“scott”这种小写且加了双引号那么连接时就必须写双引号、密码里是否有特殊字符被properties文件转义掉了、以及代码里是否真的覆盖了配置文件里的值。ORA-28000就更有意思了报错是“账户已锁定”。看到这个错先别去猜密码因为很多时候密码没错只是数据库的登录失败计数超过了阈值或者DBA手工锁定了账号。处理方式是让DBA把账户解锁或者拿system账号执行alter user scott account unlock。我自己还见过一种情况管理员改密码之后应用代码里用的仍然是旧密码失败次数累加到最后被数据库锁定。所以改密码和应用代码要同步推进最好在发布窗口里做完立刻验证连接避免锁号连锁反应。5.4 ORA-00942和ORA-00904表和列的名字匹配问题这两个错通常出现在建表之后第一次写代码时。ORA-00942是表或视图不存在ORA-00904是字段名无效。排查时先把SQL复制到数据库客户端里手动执行一遍如果客户端可以Java不行那问题出在代码的SQL语句拼接最典型的错误就是SQL字符串里多了个空格、少了空格、或者用中文引号包住了列名。如果客户端执行也报同样错那就是SQL本身的问题比如表名写错或者当前登录用户没有访问这个表的权限。Oracle对大小写的处理有它的一套规则不加双引号的情况下表名和列名存储时都被转成大写。如果你建表时用了小写加双引号后面查询时列名不加双引号就永远提示“字段无效”。这一点极其容易让从MySQL转过来的人崩溃MySQL里大小写不敏感Oracle却敏感而且敏感的规则还分双引号有无。我的原则是所有建表SQL的表名、列名统一大写不写双引号Java代码里也全部大写彻底避开这个问题。6. 资源管理与代码封装从能跑到跑得稳的最后一步增删改查都能跑了代码看起来也没问题了但我会在代码评审时还盯着两个点不放连接关闭是否彻底、连接参数是否可配置。这两个点解决好才叫真正拿得出手的数据库访问代码。6.1 try-with-resources与手动关闭的取舍先来直观对比一下两种资源关闭写法。手动关闭的代码从JDBC 1.0时代就得这么写Connection conn null; PreparedStatement ps null; ResultSet rs null; try { conn DriverManager.getConnection(URL, USER, PASSWORD); ps conn.prepareStatement(sql); rs ps.executeQuery(); while (rs.next()) { // 处理数据 } } catch (SQLException e) { e.printStackTrace(); } finally { // 层层判断非空再逐个关闭 try { if (rs ! null) rs.close(); } catch (SQLException e) { e.printStackTrace(); } try { if (ps ! null) ps.close(); } catch (SQLException e) { e.printStackTrace(); } try { if (conn ! null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } }注意关闭顺序先关闭ResultSet再关闭Statement最后关闭Connection。顺序乱了虽然不一定立刻报错但在某些Oracle驱动版本下直接关闭Connection会导致Statement和ResultSet无法正常释放连接也不会真正归还给连接池。自动关闭版本就清爽得多。我前面展示的代码里那组try-with-resources在try后面的括号里同时声明Connection、PreparedStatement、ResultSet三个资源。如果这些对象都实现了AutoCloseable接口Java会在try代码块执行完毕后以与声明顺序相反的顺序自动调用close也就是先关闭ResultSet再关闭Statement最后关闭Connection语义正好跟手动关闭完全一致。try (Connection conn DriverManager.getConnection(URL, USER, PASSWORD); PreparedStatement ps conn.prepareStatement(sql)) { try (ResultSet rs ps.executeQuery()) { while (rs.next()) { // 处理数据 } } } catch (SQLException e) { e.printStackTrace(); }别小看这个语法糖。我见过太多因为finally里写错关闭顺序导致连接泄漏的案例try-with-resources直接在设计上帮你把这种问题消灭了。6.2 写一个顺手且安全的工具类为了不让每个DAO类里都重复写一遍驱动加载和连接获取我习惯把所有连接相关逻辑收敛到一个独立的工具类里前面配置文件的读取也一并揉进去。这样每个业务类只需要几行代码就能拿连接而且换环境不用改任何Java文件。import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; public class DBUtil { private static String url; private static String username; private static String password; static { try (InputStream in DBUtil.class.getClassLoader().getResourceAsStream(db.properties)) { Properties props new Properties(); props.load(in); url props.getProperty(jdbc.url); username props.getProperty(jdbc.username); password props.getProperty(jdbc.password); Class.forName(props.getProperty(jdbc.driver)); } catch (Exception e) { throw new ExceptionInInitializerError(e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, username, password); } }对应的db.properties文件放在src根目录jdbc.driveroracle.jdbc.OracleDriver jdbc.urljdbc:oracle:thin://192.168.1.100:1521/orcl jdbc.usernamescott jdbc.passwordtiger这里有一个值得注意的设计细节静态初始化块里读取配置并加载驱动无论项目里有多少个类调用DBUtil驱动只会被加载一次。Class.forName这个方法重复调用不会有副作用但能省就省。从工程角度讲这个工具类同时完成了配置外部化和驱动统一加载两件事团队成员写代码时只要严格遵守“连接用完即关”的原则数据库连接问题会减少一大半。6.3 从控制台到文件日志让Oracle报错能被复现最后一个建议来自我在实际项目中吃过的亏。Eclipse控制台里打印的Oracle报错信息在这个会话里能看到关掉之后什么都留不下来。一旦出问题想复盘你会发现自己对着一个空白控制台无从下手。建议从项目一开始就把Java的日志框架配置好至少保证SQLException的堆栈信息能写进文件。java.util.logging、Log4j、Slf4j随便选一个重点是可以按时间和级别检索报错。排查Oracle连接问题时日志里至少要记录这几个信息错误代码e.getErrorCode()、SQL状态e.getSQLState()、完整堆栈、以及触发这条SQL的业务方法名。有了这几个维度就能快速定位到具体哪一次操作触发了数据库错误而不是在一堆代码里瞎猜。我在实际工作中最舒服的调试流程是这样的开发环境里先用上面那个DBUtil测通连接接着在一个独立的测试类里逐条执行CRUD每步都打印日志确认无误后再把DAO方法接到业务代码上。这么做的好处是一旦出问题排查范围被缩得很小——要么是SQL语句问题要么是业务传参问题绝不会出现一堆代码在一起让人无从下手的局面。讲到这基本覆盖了Eclipse接Oracle从环境配置到增删改查再到排障的全过程。最后再分享一个小技巧如果你用的数据库是Oracle 12c以上的版本排序和分页可以直接用OFFSET FETCH子句比传统的ROWNUM写法简单很多代码可读性强一个档次而且这套语法在未来的Oracle版本里是主流方向早点用起来不吃亏。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑