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 Thin方式连接Oracle - 图1

图 22.2 JDBC Driver下载页面

企业中Java操作Oracle的开发最常用的就是第4类驱动,也叫JDBC Thin类型。它比较方便,客户投资低,效率高,开发者接受快。接下来看如何用该方式连接Oracle。

笔者将使用Eclipse作为开发工具,演示使用Java语言如何访问Oracle 11g,分为新建工程、导入数据库驱动包、创建配置文件、创建数据库连接初始化文件、创建数据库连接类以及编写测试类6个步骤。

(1)新建工程

首先打开Eclipse开发工具,选择图22.3所示的菜单,新建一个Java工程。这里新建一个Java工程,用默认选项即可。这里工程取名为MyDbDemo。

22.2 Thin方式连接Oracle - 图2

图 22.3 新建Java工程

(2)导入数据库驱动包

右击该项目名称,从弹出的快捷菜单中选择【Properties】选项,出现图22.4所示界面。

22.2 Thin方式连接Oracle - 图3

图 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