22.2 Thin方式连接Oracle
前面介绍过,想要用JDBC连接数据库就要有该数据库的JDBC Driver支持,通常它以jar文件的形式提供。这一点需要注意。
目前绝大部分的数据库都提供了JDBC Driver,如Oracle、DB2、MySQL等,但不同类型的数据库驱动是不一样的(甚至同种类型数据库不同版本之间的驱动名称也是不一样的,具体情况可以查看各数据库官方网站)。Oracle 11g自带JDBC驱动分为针对JDK 1.5(ojdbc5.jar)的版本和JDK 1.6的版本(ojdbc6.jar)。
如果安装了Oracle 11g,可以到c:\app\Administrator\product\11.1.0\db_1\jdbc\lib目录下查看自带驱动(该目录根据第2章安装目录查找),如果没有安装Oracle 11g,则可以到Oracle官方网站根据需求下载JDBC驱动。下载地址为http://www.oracle.com/technology/global/cn/software/tech/java/sqlj_jdbc/htdocs/jdbc_111060.html。这里笔者根据自己的JDK版本(JDK 1.5)选择下载黑框部分(图22.2中)的ojdbc5.jar文件,以便示例中使用。JDBC Driver下载页面如图22.2所示。
图 22.2 JDBC Driver下载页面
企业中Java操作Oracle的开发最常用的就是第4类驱动,也叫JDBC Thin类型。它比较方便,客户投资低,效率高,开发者接受快。接下来看如何用该方式连接Oracle。
笔者将使用Eclipse作为开发工具,演示使用Java语言如何访问Oracle 11g,分为新建工程、导入数据库驱动包、创建配置文件、创建数据库连接初始化文件、创建数据库连接类以及编写测试类6个步骤。
(1)新建工程
首先打开Eclipse开发工具,选择图22.3所示的菜单,新建一个Java工程。这里新建一个Java工程,用默认选项即可。这里工程取名为MyDbDemo。
图 22.3 新建Java工程
(2)导入数据库驱动包
右击该项目名称,从弹出的快捷菜单中选择【Properties】选项,出现图22.4所示界面。
图 22.4 导入Oracle驱动包
单击【Add External JARs】按钮,找到ojdbc5.jar文件,选中后单击【打开】按钮,回到图22.4。单击【OK】按钮,这样Oracle 11g的JDBC驱动就加载到了工程中。
注意 如果没有把ojdbc5.jar文件加入到该工程,会提示数据库驱动有问题。上面的这种方法只是临时方法,一般都是把该包文件直接复制到工程下,然后加载即可。
(3)创建配置文件
在工程中的src目录下创建一个名字为db_config.properties的文件,在该文件中存放Oracle的连接配置信息。这样当改动目标数据库时不用修改Java代码。具体内容如下:
Oracle
drivers=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@192.168.128.130:1521:ORCL
user=scott
pwd=tiger
【代码解析】
❑oracle.jdbc.driver.OracleDriver:Oracle连接驱动字符串。在代码中将获取该变量以加载Oracle数据驱动。
❑jdbc:oracle:thin:@192.168.128.130:1521:ORCL:Oracle数据库连接URL。其中具体描述了要连接的目标数据库。其中,“192.168.128.130:1521”是数据库所在机器IP以及端口,"ORCL"是数据库SID。
❑scott:登录数据库的用户名。
❑tiger:登录数据库的密码。
(4)创建数据库连接初始化文件
在工程src目录下创建com.db包,再创建DBConfig.java文件。代码如下:
01 public class DBConfig{
02
03 private static String db_config="db_config.properties";
04 public static String DRIVERS=null;
05 public static String URL=null;
06 public static String USER=null;
07 public static String PASSWORD=null;
08
09 static{
10
11 Properties props=new Properties();
12 InputStream inStr=null;
13
14 try{
15 //读取属性文件
16 inStr=ClassLoader.getSystemResourceAsStream(db_config);
17
18 //读取属性列表
19 props.load(inStr);
20 }catch(IOException e){
21 //TODO Auto-generated catch block
22 e.printStackTrace();
23 }
24
25 DRIVERS=props.getProperty("drivers");//得到Oracle连接驱动字符串
26 URL=props.getProperty("url");//得到Oracle数据库连接URL
27 USER=props.getProperty("user");//得到用户名
28 PASSWORD=props.getProperty("pwd");//得到密码
29 }
30
31 }
【代码解析】
❑以上代码从db_config.properties文件中得到对应的数据,用于进行Oracle连接的初始化工作。为了使用方便,这里把变量声明成了静态变量。
❑第1行定义了一个类,名为DBConfig。
❑第3~7行表示声明类的属性,也就是变量,并为其进行初始化。
❑第9~29行是一个静态代码块。这里的功能主要是获取数据库连接参数,并赋值给第3~7行声明的变量。
❑第11行表示创建一个属性文件操作类的实例,名为props。
❑第12行表示声明一个输入流的对象。
❑第14行表示捕捉try后面的大括号内所有代码可能出现的异常。
❑第20~23行表示异常处理区。
❑第16行表示把属性文件转换成流文件。
❑第19行表示利用props对象,读取db_config.properties文件内的数据。
❑第25~28行表示为DBConfig类的属性赋值。
(5)创建数据库连接类
数据库连接类的功能包括打开数据库连接和关闭连接。具体代码如下:
01 import java.sql.Connection;
02 import java.sql.DriverManager;
03 import java.sql.SQLException;
04
05 public class DBConnection{
06 private static String drivers=DBConfig.DRIVERS;
07 private static String url=DBConfig.URL;
08 private static String user=DBConfig.USER;
09 private static String password=DBConfig.PASSWORD;
10
11 /**
12 *获取数据库连接,返回Connection对象
13 *
14 *@return
15 */
16 public static Connection GetConnection(){
17 Connection conn=null;
18 try{
19 //这里使用Class.forName()方法创建驱动程序的实例并且自动调用DriverManager对其注册
20 Class.forName(drivers).newInstance();
21 }catch(InstantiationException e){
22 e.printStackTrace();
23 }catch(IllegalAccessException e){
24 e.printStackTrace();
25 }catch(ClassNotFoundException e){
26 e.printStackTrace();
27 }
28
29 try{
30 //通过DriverManager获取数据库连接
31 //这里getConnection方法里面的3个参数均来自db_config.properties文件
32 System.out.println("url=="+url);
33 System.out.println("user=="+user);
34 System.out.println("password=="+password);
35 conn=DriverManager.getConnection(url,user,password);
36 }catch(SQLException e){
37 e.printStackTrace();
38 }
39
40 return conn;
41 }
42
43
44 /**
45 *关闭连接
46 *
47 *@param conn
48 */
49 public static void close(Connection conn){
50 try{
51 if(conn != null&&!conn.isClosed())
52 conn.close();
53 }catch(SQLException e){
54 e.printStackTrace();
55 }
56 }
57 }
【代码解析】
❑该类的主要功能是对“数据库连接”进行控制,包括获取、打开数据库连接以及关闭数据库连接。
❑第1~3行表示引入其他工具类,它们分别是Connection类、DriverManager类、SQLException类。
❑第5行表示创建数据库连接控制类,名为DBConnection。
❑第6~9行表示创建类变量并为其初始化数据,这些变量所代表的含义和DBConfig类中同名的变量含义相同。
❑第11~15行是对方法GetConnection的注释。
❑第16~41行属于方法GetConnection。该方法是一个静态方法。
❑第17行表示声明一个局部变量,变量名为conn,变量类型为Connection。
❑第20行表示注册驱动程序。这里使用了Java的反射机制,得到了"oracle.jdbc.driver.OracleDriver"的实例。
❑第32~34行表示输出数据结果到屏幕,可供参考。
❑第35行表示利用指定的数据库URL、用户名、密码得到数据库连接,以供外部调用。
❑第49行表示创建关闭连接的方法close。数据库连接一旦用完,要么回归连接池,要么关闭,否则会出现内存泄露等情况。
说明 使用反射的方式实现并不是唯一方式,这样写的目的是可以重用该部分代码。真实的操作过程是这样的:
1)创建oracle.jdbc.driver.OracleDriver的实例。
2)在实例化OracleDriver时Oracle提供的驱动中会利用DriverManager.registerDriver()对其自己创建的OracleDriver实例进行注册。
3)利用DriverManager的getConnection方法得到数据库连接。
以上步骤要从上到下顺序执行。
(6)编写测试类
下面做一个测试类,查询Oracle 11g中scott用户下表DEPT的数据。代码如下:
01 import java.sql.Connection;
02 import java.sql.PreparedStatement;
03 import java.sql.ResultSet;
04 import java.sql.SQLException;
05 import java.sql.Statement;
06
07 public class DBTest{
08
09 /**
10 *测试方法
11 */
12 public void TestDb(){
13 Connection conn=null;//声明Connection对象
14 PreparedStatement pstmt=null;//声明PreparedStatement对象,用来存储预编译语句
15 ResultSet rs=null;//声明ResultSet对象
16 try{
17 conn=DBConnection.GetConnection();//得到连接
18 pstmt=getStatement(conn,"SELECT DEPTNO,DNAME FROM DEPT");
19 rs=executeQuery(pstmt);//执行查询
20 while(rs.next()){
21 System.out.println(rs.getString("DEPTNO")+"==="
22 +rs.getString("DNAME"));
23 }
24
25 }catch(SQLException e){
26 System.out.println(e.toString());
27 e.printStackTrace();
28 }finally{
29 close(rs);//关闭结果集
30 close(pstmt);//关闭语句
31 DBConnection.close(conn);//关闭连接
32 }
33 }
34
35 /**
36 *得到PreparedStatement对象
37 *
38 *@param conn
39 *@param strsql
40 *@return
41 */
42 public static PreparedStatement getStatement(Connection conn,String strsql){
43 if(strsql==null||"".equals(strsql)){
44 System.out.println("SQL为空…");
45 return null;
46 }
47 if(conn==null){
48 System.out.println("连接为空…");
49 return null;
50 }
51
52 try{
53 return conn.prepareStatement(strsql,//预编译语句得到PreparedStatement对象
54 ResultSet.TYPE_SCROLL_INSENSITIVE,
55 ResultSet.CONCUR_UPDATABLE);
56 }catch(SQLException e){
57 //TODO Auto-generated catch block
58 e.printStackTrace();
59 }
60 return null;
61 }
62
63 /**
64 *得到ResultSet
65 *
66 *@param pstmt
67 *@return
68 */
69 public static ResultSet executeQuery(PreparedStatement pstmt){
70 try{
71 if(pstmt != null)
72 return pstmt.executeQuery();//查询
73 }catch(SQLException e){
74 //TODO Auto-generated catch block
75 e.printStackTrace();
76 }
77 return null;
78 }
79
80 /**
81 *关闭Statement对象
82 *
83 *@param stmt
84 */
85 public static void close(Statement stmt){
86 try{
87 if(stmt != null){
88 stmt.close();
89 }
90 }catch(SQLException e){
91 e.printStackTrace();
92 }
93 }
94
95 /**
96 *关闭结果集
97 *
98 *@param rs
99 */
100 public static void close(ResultSet rs){
101 try{
102 if(rs != null){
103 rs.close();
104 }
105 }catch(SQLException e){
106 e.printStackTrace();
107 }
108 }
109 }
【代码解析】
❑代码中一共有5个方法,根据业务可以拆分成两个类,但为了讲述方便这里不做拆分。
❑第1~5行表示引入的外部类。
❑第12行的TestDb是一个测试方法。执行过程如下:
1)调用连接方法,得到数据库连接。
2)得到PreparedStatement对象。
3)执行查询得到ResultSet对象。
4)利用ResultSet的next()方法,迭代输出结果集内容。
5)依序关闭ResultSet对象、PreparedStatement对象、Connection对象。
❑第42行的getStatement()方法是根据数据库连接和SQL语句得到PreparedStatement对象,其核心语句是连接调用PreparedStatement方法部分,其中的后面两个参数是为了生成允许滚动和允许更新的ResultSet对象(默认情况下是不允许的)。调用该方法把SQL语句传给Oracle进行预编译,为查询做准备,在频繁执行该SQL语句时此种方式效率比较高。
❑第69行的executeQuery()方法的主要工作是执行查询语句,从Oracle中得到数据。通常称其为“结果集”,结果集中的数据可以利用迭代语句得到。
❑第85行和第100行是两个关闭方法。这两个close方法利用了Java的方法重载原理,分别负责关闭Statement类型对象和结果集。
注意 当执行完查询结果时要按顺序关闭ResultSet、PreparedStatement、Connection 3个对象,特殊情况除外,否则会造成资源的浪费,直到连接不上Oracle。
执行结果如下:
10===ACCOUNTING
20===RESEARCH
30===SALES
40===OPERATIONS