
6.1 Weblogic Server支持的JDBC
6.1.1 JDBC简介
JDBC可做三件事:
●与数据库建立连接
●发送SQL语句
●处理结果
使用JDBC要引入:两个程序包:
●java.sql:核心API
●javax.sql:扩展API
6.1.2 JDBC的结构
JDBC主要包括:Connection、Statement、Resultset类。
JDBC应用程序的工作方式:
1.加载数据库的JDBC驱动程序(由DriverManager类管理)
2.建立Connection
3.由连接建立语句对象(Statement、PreparedStatement、CallabelStatement)
4.由语句建立结果集对象Result
5.通过语句对象和结果集对象进行各种数据操作
6.关闭连接
Callabel
Statement
Statement
DriverManager
ResultSet
Prepared
Statement
ResultSet
ResultSet
JDBC驱动程序
数据库
图4-1 JDBC应用示意图
6.1.2.1 JDBC驱动程序
JDBC是一个面向Java开发人员的类似于ODBC的数据库访问接口,只支持Java程序。
1. 类型1驱动程序
此种驱动程序把JDBC翻译成ODBC调用。
优点:可以访问ODBC能访问的所有数据库
缺点:执行效率比较低
数据库
网络库
ODBC
驱动程序
类型1
JDBC驱动程序
应用程序
(JAVA)
2. 类型2驱动程序
直接将应用程序与网络库连接,这样,必须在使用此驱动程序的计算机上安装网络库。类型2驱动程序的性能优于类型1驱动程序。
数据库
网络库
类型2
JDBC驱动程序
应用程序
(JAVA)
3. 类型3驱动程序
类型3驱动程序将应用程序与中间件服务器(如Weblogic Server)连接,进而允许客户与后端多个数据库连接。为了做到这一点,中间件服务器将应用程序的JDBC调用映射到适当的数据库驱动程序上。这些数据库驱动程序安装在中间件服务器上,而不是在客户机上。
优点:客户机不需要安装网络库。
Weblogic Server的Pool驱动程序就是此类型。
4.类型4驱动程序
把JDBC操作直接转换成不使用ODBC或本机API的本机协议。这种驱动程序是完全用java实现的,不需要其它驱动程序和客户端网络库。此类驱动程序是数据库厂商提供的,能够提供对于相应数据库系统的最优化的访问。
数据库
类型4
JDBC驱动程序
应用程序
(JAVA)
第三种和第四种是将来的发展方向
6.1.2.2 连接
连接是客户端Java代码和数据库之间的通信连接,由JDBC驱动程序建立。
1. 直接连接
是直接在客户端Java代码中打开并维护的,对应于类型1、2、4。使用直接连接必须在完成对数据库的操作后将连接关闭。否则,太多的连接将导致系统性能下降甚至超过数据库服务器的连接。
2. 池连接
是被J2EE服务器打开和维护的。J2EE启动时会建立一定数量的池连接,并一直维持不少于此数目的池连接。客户端程序需要连接时,池驱动程序会返回一个未使用的池连接并将其标记为忙。如果当前没有空闲的连接,池驱动程序就新建一定数量的连接。当连接的调用完成后,池驱动程序将此连接标记为空闲。
优点:比直接连接更有优越性,提高了性能同时节省了宝贵的资源。
6.1.2.3 语句
●简单语句:与java.sql.Statement接口相对应,用来执行简单SQL命令
●预编译语句:与java.sql.PreparedStatement接口相对应,可以使用被预编译的SQL语句,以提高效率
●可调用语句:与java.sql.CallableStatement接口相对应,用于调用存储过程。
6.1.2.4结果集
与java.sql.ResultSet接口相对应,存储语句对象发出查询命令的结果集。可用一套get/set方法访问结果集行中的数据。
6.1.3使用JDataStore数据库
JdataStore的扩展名为jds,安装在Jbuilder目录下的samples\\Jdatastore\\datastores目录中,如:employee.jds数据库
6.1.3.1JDataStore Server
启动:开始--- Jbuilder菜单组---JDataStore Server
用Jbuilder附带的JdataStore数据库,同时只能有一个连接连到数据库。
6.1.3.2JDataStore Explorer
使用他可以完成创建JdataStore数据库、查看JdataStore数据库、修改JdataStore数据库中的记录。
启动:可通过Jbuilder菜单组中的JDataStore Explorer菜单项
1.查看JDataStore数据库
File---Open菜单项
选定文件(employee.jds)
输入user name:example
password:
2.执行SQL语句
连接到数据文件后,单击Tools—SQL菜单项或单击工具栏中的”SQL“图标可以进入SQL窗口。在SQL窗口中输入要执行的SQL语句,然后单击〔Execute〕按钮即可执行SQL语句。
3.新建数据库
单击〔File〕---〔New〕菜单项,输入新建数据库文件的路径及名称、数据库文件的版本信息等。
6.1.4WebLogic Server中的JDBC配置
配置连接池和数据源。数据源相当于客户端程序和连接池的中介,要想获得连接池中的连接对象,必须建立一个与该连接池相应的数据源,然后通过数据源获得连接。
在Weblogic中开发JDBC的步骤如下:
(1)建立到指定数据库的连接池,连接池中封装了连接数据库的一些信息,如JDBC驱动程序、数据库名字、账号/密码。
JNDI Tree
RMI
RMI
TxDataSource
DataSource
Connection
Connection
Connection
Connection
Pool
Lookup Data Source or
TxData Source
WebLogic Server
图6-12 WebLogic Server 中的JDBC应用
Internal Clients(e.g.,servlets)
External
Clients
Type 2 or Type 4
JDBC Driver
DataBase
(2)建立基于某个连接池的数据源,该数据源的名字可以通过JNDI查找
(3)访问数据库时通过数据源的JNDI名字查找到该数据源,然后通过数据源获得连接。得到连接后,就可以依次生成语句和结果集。
使用连接池的好处:
●节省时间:建立数据库连接费时,事先建好的连接可节省时间
●封装用户信息:账号和密码已经封装在连接池中,客户端程序在建立连接时不用考虑安全信息。
6.1.4.1 配置连接池
在Weblogic Server管理控制台中完成。步骤如下:
1.启动Weblogic Server Admin Console。在左侧域树中选择“JDBC”---“Connection Pools”
2.单击configuration a new JDBC connection
选择database type:oracle
database driver:oracle’s driver (thin)version:8.17,9.0.1,9.20
3.在连接池信息配置界面中完成有关连接池的各项配置:
●name:(连接池的名称)
●connection properties:
databse name:student
host name:localhost
port:1521
database user name:scott
password:tiger
confirm password:tiger
4.测试连接
create and deploy
5.配置connections选项卡
initial capacity:连接池中的初始连接数。默认值为1
maximum capacity:连接池中最大连接数。默认值为1
capacity increment:每次增加的连接数
login delay seconds:池驱动程序在启动时打开每一个新的连接需要等待的时间。
Refresh period:刷新周期。如果输入非零值,每隔所设值的时间就将已打开但还未被使用的数据连接关闭,然后重新打开,以检测数据库是否可用。
6.1.4.2 配置数据源
单击管理控制台左侧域树中的JDBC-Data sources项,单击右侧窗口中的configure a new jdbc source…超级链接。
Name:(jdbc数据源的名称)MyJDBC Data Source
JNDI Name:ds_student
Honor global transactions:指定数据源是否参加现存的全局事务。
Pool name:此数据源对应的connection pool的名字。
Row prefetch enabled:是否允许行预取。
Row prefetched size:行预取大小
Stream chunk size:流块大小
选择要发布数据源的服务器(myserver)。
单击create按钮。
6.1.4.3 配置tx数据源(Tx data source)
Tx data source是支持分布式事务的数据源。与参加数据源类似。
单击管理控制台左侧域树中的JDBC-Tx Data sources项,单击右侧窗口中的configure a new jdbc Tx source…超级链接。
Name:(jdbc数据源的名称)MyJDBC Data Source
JNDI Name:ds_student
Pool name:此数据源对应的connection pool的名字。
6.2 weblogic server下的JDBC开发实例
步骤:
(1)建立连接
(2)执行SQL语句
(3)处理结果集
(4)关闭连接
6.2.1 建立连接
6.2.1.1 查找datasource对象
通过datasource的JNDI名字查找datasource对象
6.2.1.2 获得数据库连接
通过datasource类的getConnection()方法获得数据库连接。
Connection myConn = ds.getConnection();
6.2.1.3 建立连接的代码实例
DataSource ds=null;
Context ctx=null;
Connection myConn=null;
Try {
Ctx=getInitialContext();
//查找JNDI名字为ds_student的数据源
ds=(javax.sql.DataSource)ctx.lookup(“ds_student”);
}
catch (Exception E) {
System.out.println(“init Error:”+E);
}
try {
myConn=ds.getConnection();
}
catch (Exception E)
{ System.out.println(“init Error:”+E);
}
6.2.2 执行SQL语句
执行sql语句是通过Statement完成的。建立Statement对象可以通过Connection对象的createStatement方法完成。建立Statement对象后可以调用其executeQuery和executeUpdate方法执行sql语句。这两个方法的区别是executeQuery执行的是查询语句,返回一个ResultSet对象,而executeUpdate执行的是更新数据库的操作(如删除数据、修改数据),无返回值。
例:
Statement stmt=con.createStatement();
Stmt. ExecuteUpdate(“insert into table1 values(v1,v2)”);
6.2.3 处理结果集
6.2.3.1 取当前记录的列值
ResultSet类提供了一系列get方法(每一种数据类型对应一个get方法),使用与列数据类型对应的get方法可以取得该列的值。如rs.getString(“a”)返回当前记录a列的值。
6.2.3.2 结果集的滚动
ResultSet对象提供了next方法,向后滚动一条记录。结果集刚建立时,当前记录并不是第一条记录,而是位于第一条记录之前。遍历结果集可用一个while循环完成。
While (rs.next()) { }
6.2.4 关闭连接
使用Connection对象的close方法关闭连接。
6.2.5 开发实例
6.2.5.1 实例1
开发步骤
(1)在jbuilder 9中新建一个工程jdbc_pj1
(2)添加一个class,名称为class1在该文件中添加以下代码:
package jdbc_pj1;
import java.sql.*;
import javax.naming.*;
import javax.sql.*;
import java.util.Properties;
import javax.rmi.PortableRemoteObject;
public class class1 {
public static void main(String args[])
{
DataSource ds=null;
Context ctx=null;
Connection myConn=null;
try {
ctx=getInitialContext();
ds=(javax.sql.DataSource)ctx.lookup("ds_student");
}
catch (Exception E)
{
System.out.println("init error:"+E);
}
Statement myStatement=null;
ResultSet myResultSet=null;
try {
myConn=ds.getConnection();
myStatement=myConn.createStatement();
myResultSet=myStatement.executeQuery("SELECT ename from emp");
while (myResultSet.next() )
System.out.println("the employee name is "+myResultSet.getString("ename"));
myResultSet.close();
}
catch (SQLException e)
{
System.out.println("error code= "+e.getErrorCode());
System.out.println("error message="+e.getMessage() );
}
finally {
try {
if (myStatement !=null)
myStatement.close();
if (myConn!=null)
myConn.close();
}
catch (SQLException e)
{
System.out.println("error code= "+e.getErrorCode());
System.out.println("error message="+e.getMessage() );
}
}
}
private static Context getInitialContext() throws Exception
{
String url="t3://localhost:7001";
String user="system";
String password="security";
Properties properties=null;
try
{
properties=new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
properties.put(Context.PROVIDER_URL,url);
if (user!=null)
{
properties.put(Context.SECURITY_PRINCIPAL,user);
properties.put(Context.SECURITY_CREDENTIALS,password==null?"":password);
}
return new InitialContext(properties);
}
catch (Exception e)
{
throw e;
}
}
}
(3)编译、运行该文件
6.2.5.2 实例2
本例将演示如何显示数据库中emp表的数据结构并显示所有记录。开发步骤与上例相同,只不过把main方法中的代码用以下代码替换为:
package jdbc_pj1;
import java.sql.*;
import javax.naming.*;
import javax.sql.*;
import java.util.Properties;
import javax.rmi.PortableRemoteObject;
public class class2 {
public static void main(String[] args) {
DataSource ds=null;
Context ctx=null;
Connection myConn=null;
try {
ctx=getInitialContext();
ds=(javax.sql.DataSource)ctx.lookup("ds_student");
}
catch (Exception E)
{
System.out.println("init error:"+E);
}
Statement myStatement=null;
ResultSet myResultSet=null;
try {
myConn = ds.getConnection();
myStatement = myConn.createStatement();
myResultSet = myStatement.executeQuery("SELECT * from emp");
for (int j=1;j<=myResultSet.getMetaData().getColumnCount();j++)
System.out.print(myResultSet.getMetaData().getColumnName(j)+"\");
System.out.println();
while (myResultSet.next())
{
for (int j=1;j<=myResultSet.getMetaData().getColumnCount();j++)
System.out.print(myResultSet.getObject(j)+"\");
System.out.println();
}
myResultSet.close();
}
catch (SQLException e)
{
System.out.println("error code= "+e.getErrorCode());
System.out.println("error message="+e.getMessage());
}
finally {
try {
if (myStatement !=null)
myStatement.close();
if (myConn!=null)
myConn.close();
}
catch (SQLException e)
{
System.out.println("error code= "+e.getErrorCode());
System.out.println("error message="+e.getMessage() );
}
}
}
private static Context getInitialContext() throws Exception
{
String url="t3://localhost:7001";
String user="system";
String password="security";
Properties properties=null;
try
{
properties=new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
properties.put(Context.PROVIDER_URL,url);
if (user!=null)
{
properties.put(Context.SECURITY_PRINCIPAL,user);
properties.put(Context.SECURITY_CREDENTIALS,password==null?"":password);
}
return new InitialContext(properties);
}
catch (Exception e)
{
throw e;
}
}
}
6.3 Weblogic Server中的得事务处理
6.3.1 事务的基本理论
6.3.1.1 事务综述
1.事务产生的动机
(1)保证操作的原子性
(2)网络故障或机器故障
(3)数据共享
需要一种机制来保证多用户并发访问数据的问题
以上这些问题的解决方法,就是使用事务服务
2.使用事务服务带来的好处
(1)原子性
(2)一致性
(3)隔离性
(4)持久性
6.3.1.2 使用事务服务的应用
使用事务服务的应用由下列实体组成:
(1)事务客户
(2)事务对象:在事务范围内行为会被影响的对象
(3)可恢复对象和资源对象:如果事务的提交和回滚将影响某个对象里面的数据,则这个对象称为可恢复对象。可恢复对象必须将自己注册为事务服务中的一个资源对象,才可以参与到事务中。
(4)提供事务支持的服务器
(5)可恢复资源服务器
6.3.1.3 事务服务提供的功能
1.事务服务提供的操作
(1)控制事务的范围和持续的时间
(2)让多个对象参与到一个单独的原子性事务中
(3)将对象内部状态的改变同事务相联系
(4)协调事务完成
2.事务模型
(1)平面型事务模型
整个事务是一个整体,不可划分为子事务
(2)嵌套式事务模型
嵌套有子事务,子事务中还可以嵌套子事务,整体是一个树型结构。如:旅行计划问题:
●购买从美国波士顿到美国纽约的火车票
●购买从美国纽约到英国伦敦的飞机票
●购买从英国伦敦到法国巴黎的飞艇票
●发现没有飞往法国巴黎的飞艇票
这对于平面型事务来说,只能有一个选择:事务失败。但是在这里,可以采用其它的旅行方式代替飞艇。因此需要一个更加健壮的事务模型解决这个问题。可以将这个事务划分为若干个子事务,整个事务可以重新执行单个子事务尝试完成事务,如果最终某个单个子事务无法完成,则整个事务失败。
(3)其它事务模型
锁链式模型、传奇式模型等
3.事务的终止
commit或rollback
4.事务的完整性
5.事务的上下文
6.3.1.4 分布式事务
分布式事务是指事务的参与者、支持事务的服务器、资源服务器及事务管理器分别位于不同的分布式系统的不同结点之上。为了实现分布式事务,需要使用下面介绍的两阶段提交协议。
(1)阶段一:开始向事务涉及到的全部资源发送提交信息。
6.4 JDBC的高级话题
6.4.1 使用PreparedStatement
1.建立预编译语句对象
PreparedStatement pst=con.prepareStatement(“insert into testable values(?1,?2)”);
2. 使用预编译语句执行sql语句
使用PreparedStatement的execute方法就可以执行该预编译语句对象所对应的sql语句。如果预编译语句对象建立时相应的SQL语句有参数,则在使用是首先要给参数赋值。给参数赋值通过setXXX方法完成的。String类型的参数用setString方法赋值。
Pst.setString(1,”value1”);
Pst.setString(2,”value2”);
Pst.execute();
6.4.2 使用JDBC存储和调用大对象
6.4.2.1 BLOB 和CLOB
使用BLOB、CLOB可以有以下好处:
●提供一种方便的方法、把大量的数据表示为单个数据库对象
●数据库系统通常会对这两种数据类型做优化处理
6.4.4.2.2 使用BLOB和CLOB
下面讲述通过ResultSet访问BLOB和CLOB类型的数据
(1)建立BLOB和CLOB对象:
java.sql.BLOB myBlob=null;
java.sql.CLOB myClob=null;
(2)通过ResultSet的getBLOB和getCLOB方法获得记录中的BLOB、CLOB类型的数据;如:
myBlob=rs.getBlob(“blobcolumn”);
myClob=rs.getClob(“clobcolumn”);
(3)使用BLOB、CLOB对象
例如,以下语句可以将BLOB中封装的图像文件数据取出,生成一个ImageIcon对象,然后在Jlabel组件中显示出来。
ImageIcon icon=
new ImageIcon(myBlob.getBytes(1,(int)myBlob.length()));
jlabel1.setIcon(icon);
下面给出一个完整的BLOB、CLOB应用实例LargeObject.java。
该程序首先建立一个带有BLOB和CLOB类型列的数据表,然后分别对BLOB和CLOB列进行读写。
该实例使用的是Oracle数据库Oracle9i。在建立数据库连接时采用的是直接加载weblogic server提供的oracle数据库jdbc驱动程序Jdriver for oracle。该程序需要在本机安装oracle的客户端程序。
通过以下语句加载jdriver for oracle驱动程序并建立数据库连接:
Properties props=new Properties();
props.put("user",”scott”);
props.put("password",”tiger”);
props.put("serevr",”student”);
Driver myDriver=
(Driver)Class.forName("weblogic.jdbc.oci.Driver").newInstance();
conn=myDriver.connect("jdbc:weblogic:oracle",props);
如果在jbuilder 中运行该程序,需要将〔wl_home〕\\server\\bin\\oci901_8目录下的weblogicoci39.dll文件拷贝到jbuilder安装目录下的jdk1.4\\jre\\lib目录下。weblogicoci39.dll是weblogic server提供的Jdriver for Oracle的运行库。
以下是原代码:
package blobexample;
import java.sql.*;
import java.io.*;
import weblogic.jdbc.common.*;
import java.util.Properties;
public class LargeObject {
public static void main(String[] args) {
String user="scott";
String password="tiger";
String server="student";
java.sql.Blob myBlob=null;
java.sql.Clob myClob=null;
java.sql.Connection conn=null;
Properties props=new Properties();
props.put("user",user);
props.put("password",password);
props.put("serevr",server);
try
{//加载JDBC驱动程序:JDriver for Oracle
Driver myDriver=(Driver)Class.forName("weblogic.jdbc.oci.Driver").newInstance();
//建立数据库连接
conn=myDriver.connect("jdbc:weblogic:oracle",props);
//在使用BLOB、CLOB时需要设置连接的事务自动提交属性为false
conn.setAutoCommit(false);
//建立带有BLOB和CLOB类型字段的数据表lobtest
try
{
Statement crstmt=conn.createStatement();
System.out.println("\\nCreating table with Blobs and Clobs...");
crstmt.execute("create table lobtest(id int,blobcol Blob,clobcol Clob)");
crstmt.close();
}
catch (Exception e)
{
System.out.println("Exception:"+e);
System.out.println("Table already exists. Dropping it and re_creating...");
Statement crstmt2=conn.createStatement();
crstmt2.execute("drop table lobtest");
crstmt2.execute("create table lobtest(id int,blobcol Blob,clobcol Clob)");
crstmt2.close();
}
System.out.println("table lobtest created.");
//===初始化表中的BLOB和CLOB字段=======
Statement stmt=conn.createStatement();
System.out.println("\\ninserting row with blank blob and clob columns...");
stmt.execute("insert into lobtest values (44,EMPTY_BLOB(),EMPTY_CLOB())");
System.out.println("Row has been inserted.");
//=======生成BLOB对象myBlob==========
stmt.execute("select * from lobtest where id=44");
ResultSet rs=stmt.getResultSet();
while (rs.next())
myBlob=rs.getBlob("blobcol");
//建立一个byte型数组b,在该数组中存放一些数据
System.out.println("\\nCreating the following byte array:");
int STREAM_SIZE=10;
byte[] b=new byte[STREAM_SIZE];
for (int i=0;i b[i]=(byte)(40+(i%20)); //range 40-60 System.out.println("byte["+i+"]="+b[i]); } //将数组b存放到数据流中,然后将数据流的数据写入myBlob所代表的BLOB列中 System.out.println("\\nWriting the byte array to a stream"+"and storing it in the table as a blob..."); InputStream is=new ByteArrayInputStream(b); java.io.OutputStream os=((weblogic.jdbc.common.OracleBlob)myBlob).getBinaryOutputStream(); byte[] inBytes=new byte[STREAM_SIZE]; int numBytes=is.read(inBytes); while (numBytes>0) { os.write(inBytes,0,numBytes); numBytes=is.read(inBytes); } os.flush(); //将保存到BLOB列中的数据取出,然后存放到byte数组r中 //最后将r中数据显示出来 System.out.println("\\n Reading the blob back from the table and displaying:"); Statement readblob=conn.createStatement(); readblob.execute("selct * from lobtest where id=44"); ResultSet rsreadblob =readblob.getResultSet(); byte[] r=new byte[STREAM_SIZE]; while (rsreadblob.next()) { Blob myReadBlob=rsreadblob.getBlob("blobcol"); java.io.InputStream readis=myReadBlob.getBinaryStream(); for (int i=0;i r[i]=(byte)readis.read(); System.out.println("output["+i+"]="+r[i]); } } //以下代码演示的是CLOB的操作 //首先建立一个字符串,该字符串中的字符将会存入CLOB列中 String ss="abcdefghijklmnopqrstuvwxyz"; System.out.println("\\nCreated the following string to be stored as a clob:\\n"+ss); //将ss中的字符存入CLOB列中 stmt.execute("select * from lobtest where id=44"); ResultSet crs=stmt.getResultSet(); while (crs.next()) { myClob=crs.getClob("clobcol"); java.io.OutputStream osss=((weblogic.jdbc.common.OracleClob)myClob).getAsciiOutputStream(); byte[] bss=ss.getBytes("ASCII"); osss.write(bss); osss.flush(); } conn.commit(); //从CLOB列中读出数据并显示出来 System.out.println("\\nReading the clob back from the table and displaying:"); Statement readclob=conn.createStatement(); readclob.execute("select * from lobtest where id=44"); ResultSet rsreadclob=readclob.getResultSet(); while (rsreadclob.next()) { Clob myReadClob=rsreadclob.getClob("clobcol"); java.io.InputStream readClobis=myReadClob.getAsciiStream(); char[] c=new char[26]; for (int i=0;i<26;i++) { c[i]=(char)readClobis.read(); System.out.println("output["+i+"]="+c[i]); } } //删除建立的表lobtest System.out.println("\\nDropping table..."); Statement dropstmt =conn.createStatement(); dropstmt.execute("drop table lobtest"); System.out.println("table dropprd."); } catch (Exception e) { System.out.println("Exception was thrown:"+e.getMessage()); } finally { try { if (conn!=null) conn.close(); } catch (SQLException sqle) { System.out.println("SQLException was thrown:"+sqle.getMessage()); } } } } 6.4.2.3 利用BLOB进行图像文件存取 该例中要完成两类操作:由SaveImage.java将一个图像文件保存到数据表filetable中(filetable有两列:filename和filedata,filename存储文件名,filedata存放文件的二进制数据,filedata的类型为BLOB);由ShowImage,java通过BLOB对象将保存在表中的图像文件数据取出,然后在一个Jlabel组件中显示出来。 该程序同样使用weblogic server提供的Jdriver作为Oracle数据库的JDBC驱动程序。 下面是SaveImage.java的源程序: package imagefile; import java.sql.*; import java.util.*; import java.io.*; public class SaveImage { public static void main(String[] args) { Properties props = new Properties(); props.put("user", "scott"); props.put("password", "tiger"); props.put("server", "myoracle"); try{ Driver myDriver = (Driver) Class.forName("weblogic.jdbc.oci.Driver").newInstance(); Connection con = myDriver.connect("jdbc:weblogic:oracle" , props); con.setAutoCommit(false); File files = new File(filename); FileInputStream fis=new FileInputStream(files); PreparedStatement ps = con.prepareStatement( "INSERT INTO filetable (filename,filedata)" + "VALUES (?, ?)"); ps.setString(1, files.getName()); ps.setBinaryStream(2, fis,(int)files.length()); ps.executeUpdate(); fis.close(); ps.close(); con.close(); System.out.println("file is saved into filetable"); }catch(Exception e){e.printStackTrace();} } } 下面是ShowImage.java的源程序: package imagefile; import java.awt.*; import java.awt.event.*; import javax.swing.*; import com.borland.jbcl.layout.*; import java.sql.*; import java.util.*; import java.io.*; public class ShowImage extends JFrame { JPanel contentPane; JLabel jLabel1 = new JLabel(); XYLayout xYLayout1 = new XYLayout(); public ShowImage() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } private void jbInit() throws Exception { contentPane = (JPanel) this.getContentPane(); contentPane.setLayout(xYLayout1); Properties props = new Properties(); props.put("user", "scott"); props.put("password", "tiger"); props.put("server", "myoracle"); try{ Driver myDriver = (Driver) Class.forName("weblogic.jdbc.oci.Driver").newInstance(); Connection con = myDriver.connect("jdbc:weblogic:oracle" , props); con.setAutoCommit(false); PreparedStatement pstmt = con.prepareStatement(selectSQL) ; ResultSet rs = pstmt.executeQuery() ; rs.next() ; Blob blob = rs.getBlob("filedata") ; // Materialize BLOB onto client ImageIcon icon = new ImageIcon(blob.getBytes(1, (int)blob.length())) ; jLabel1.setIcon(icon); rs.close(); pstmt.close(); }catch(Exception e){e.printStackTrace();} this.setSize(new Dimension(400, 300)); this.setTitle("Frame Title"); contentPane.add(jLabel1, new XYConstraints(52, 40, 327, 225)); } //Overridden so we can exit when window is closed protected void processWindowEvent(WindowEvent e) { super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_CLOSING) { System.exit(0); } } public static void main(String[] args) { ShowImage showImage = new ShowImage(); showImage.setVisible(true); } } 6.5 jdbc开发时的注意事项 6.5.1 适时地关闭资源 1.关闭JDBC Connection和PreparedStatement的正确方式 Connection conn=null; ResultSet rs=null; PreparedStatement pss=null; try { conn=datasource.getConnection(USERID,PASSWORD); pss=conn.preparedStatement(“select ename from emp where eno=?”); pss.setString(1,sessionKey); rs=pss.executeQuery(); pss.close(); conn.close(); } catch (Throwable t) {//异常处理语句 } finally { try { if (pss!=null) pss.close(); } catch (Exception e){} try { if (conn!=null) conn.close(); } catch (Exception e){} } 2.错误的做法: 以下代码显示了关闭JDBC资源的错误方法。它们将在异常情况中失去正常关闭方式。这时如果抛出异常,应用程序将无法关闭JDBC连接。 Connection conn=null; ResultSet rs=null; PreparedStatement pss=null; try { conn=datasource.getConnection(USERID,PASSWORD); pss=conn.preparedStatement(“select ename from emp where eno=?”); pss.setString(1,sessionKey); rs=pss.executeQuery(); pss.close(); conn.close(); } catch (Throwable t) {//异常处理语句 } 6.5.2 尽可能使查询灵活、准确 许多性能有问题的数据库应用程序是由于SQL语句写得非常糟糕,典型的问题包括返回太多的记录和查询太笼统等。使用SQL有许多值得学习的诀窍,可以优化性能。 6.5.3 尽可能快地提交或回滚事务 在应用设计中应尽可能快地提交或回滚事务,让事务处于开发状态甚至超时不是一个好的做法,尤其是对于大型应用更是如此。
