1 JDBC连接池配置 1.1配置连接池 FOR WEBLOGIC 8.1
论坛内经常有人询问如何配置连接池的问题,这里把配置的详细过程都再重复一遍,并包含论坛内对配置连接池出现的问题回答进行整理。
STEP 1:数据库类型和驱动类型的选择,对于各种TYPE的驱动附录内容会做介绍。
STEP 2:连接池连接属性配置,连接URL,用户名/密码,数据库服务名。
STEP 3:测试连接池配置是否正确。
STEP 4:测试成功后进行部署。
STEP 5:部署成功,选择该连接进行连接池的参数配置。
STEP 6:连接池的参数配置。
配置完成后在config.xml 文件中对应的各属性解释如下:
Initial Capacity:创建连接池时所创建的数据库连接的数目。
Maximum Capacity: 连接池中连接的最大数目。
Capacity Increment: 连接池容量在最大容量限制范围内的增量。
LoginDelay: 在创建每个物理数据库连接之前要延迟的秒数。
Allow Shrinking: 将该项设置为true时,如果没有使用额外的连接,则允许连接池把容量减小到InitialCapacity。
Shrink Frequency: 在减小连接池容量之前要等待的秒数。如果将Shrink Frequency设置为true,那么也必须将Allow Shrinking设置为true。
Test Frequency: 数据库连接测试之间间隔的秒数。在每个Refresh Period时间间隔之后,如果设置了TestTableName,就会使用TestTableName测试未使用的数据库连接。
Test Reserved Connections: 如果选择了这个选项,服务器会在把连接提供给客户端之前对其进行测试。
Test Created Connections: 如果选择了这个选项,就会在创建一个JDBC连接之后和在把它添加到JDBC连接池中的可用连接列表之前,对该JDBC连接进行测试。
Test Released Connections: 如果选择了这个选项,服务器就会在把连接返回给连接池之前对其进行测试。
Test Table Name: 用于JDBC连接测试的数据库表名。如果指定了Test Frequency,并且选择了Test Reserved Connections、Test Created Connections或Test Released Connections,则Table Name是必需的。
Weblogic.codeset=GBK:编码格式
1.1.1 通过程序配置连接池
配置连接池可以通过weblogic.management.configuration.JDBCConnectionPoolMBean或者是weblogic.management.configuration.JDBCDataSourceMBeanl编程进行。
具体代码见附录部分—代码1(连接池设置)
1.1.2 通过程序查看连接池运行状态信息
配置连接池可以通过weblogic.management.configuration.JDBCConnectionPoolMBean或者编程获取运行态的信息。
具体代码见附录部分—代码2(连接池监控)
1.2配置连接池常见问题 1.2.1 连接有效性测试选项
Q:连接池配好后,启动正常,如果Connection Pool在使用过程中与数据库的联系因为网络的问题或别的原因断掉,是不是必须重新启动weblogic才能重新让Connection Pool连上数据库?我现在每次一碰到数据库连不上就要重启一次wlsServer,烦得要命。
此类问题出现的原因:
应用服务器到数据库端的网络连接不可靠;
数据库在系统运行的情况下重启动;
驱动程序的问题造成连接不可用。
A: WLS里设置连接的检查,一个是获取连接的时候检查该连接是否有效,另外一个就是释放连接的时候检查。这两个检查在配置连接池的时候都是可以设置的。
设置的参数说明:
参数名称
参数说明
参数选择值
TestConnectionsOnReserve
从连接池获取连接后是否进行有效性测试
True/false
RefreshMinutes parameter
设定connection pool的刷新时间
刷新的时间间隔
Test Table Name
测试的表名,也可以指定SQL
表名或者是SQL
1.2.2不同类型驱动的区别与选择
Q:请教console中连接池的oracle驱动程序那个多,用哪个好呢?他们的驱动程序文件分别对应LIB目录下的哪个文件?
A: BEA_HOME$/weblogic81/server/lib目录内,如果需要连接不同的数据库需要把对应的驱动程序置于该目录内。
JDBC驱动的类型与选择,在配置连接池的时候进行选择。
JDBC-1图JDBC-2图
【TYPE 1:JDBC-ODBC桥】
JDBC-1图左边的分支称为TYPE 1,即通常由Sun公司提供的JDBC-ODBC桥接器。它提供了经由一种或多种ODBC驱动进行访问的JDBC接口,而ODBC驱动,在很多情况下也即数据库的客户端,必须加载到客户机。因而,它适用于下载和自动安装Java程序不重要、实验用途或者没有其它JDBC驱动可用的情况下。执行效率比较低,对于那些大数据量存取的应用是不适合的.而且,这种方法要求客户端必须安装ODBC 驱动,所以对于基于 internet ,intranet的应用也是不合适的.因为,不可能要求所有客户都能找到ODBC DRIVER。
【TYPE 2:本地API驱动】
JDBC-1图右边的分支成为模式2,类似于JDBC-ODBC桥接器,需要加载到客户机,却是一个部分用Java实现的驱动接口。它将JDBC调用转换为对数据库(Oracle、Sybase、Informix、DB2等)客户端接口的调用。这种驱动比起TYPE 1执行效率大大提高了,但它仍然需要在客户端加载数据库厂商提供的代码库。这样就不适合基于internet的应用。
【TYPE 3:网络协议驱动】
JDBC-2图右边的分支称为TYPE 3,它同样是一个纯Java驱动,不同于TYPE 4的是基于网络协议。它的机制是将JDBC调用转换为中间网络协议,然后转换为DBMS协议。中间网络协议层起到一个读取数据库的中间件的作用,能够连接许多类型的数据库,因而是最灵活的JDBC模式。这种模式的产品比较适用于企业内部互联网,如若支持国际互联网,还需添加对安全、穿过防火墙访问等的支持。
【TYPE 4:本地协议驱动】
图2左边的分支称为TYPE 4,它一般是数据库厂商才能实现的纯Java的基于本地协议的驱动,直接调用DBMS(数据库管理系统)使用的网络协议,对于企业内部互联网来说,是一个实用的解决方案。
1.2.3 JDBC连SQL SERVER数据库的常见问题
使用TYPE4类驱动程序,目前支持两种版本的SQL SERVER
WebLogic jDriver for Microsoft SQL Server Version 7.0 and 2000, 这个版本的驱动是WEBLOGIC的默认设置,不需要做其他的配置。
支持SQL Server 7.0 和 2000.
支持新的数据类型SQL Server Version 7.0 and 2000.
WebLogic jDriver for Microsoft SQL Server Versions 6.5 and 7.0, 使用这个版本的驱动,必须在CLASSPATH路径里增加ssqlserver4v65.jar。
支持SQL Server 6.5.
支持SQL Server 7.0 但有以下两个限制: 一,是否按照6.5的语义规则 creates columns that do not allow null values. (This behavior is normal for SQL Server version 6.5.)。二,不支持新的 SQL Server 7.0数据类型。
知道了以上两点后,有些问题就能很明确了。
Q: ClassNotFoundException的错误。该错误主要是没有加载SQL SERVER的驱动程序。
A: JDBC连接SQL SERVER需要三个包:msutil.jar,msbase.jar,mssqlserver.jar,可以把这三个包拷贝到BEA_HOME$/weblogic81/server/lib目录内。
Q: [Microsoft][SQLServer 2000 Driver for JDBC]Error establishing socket的错误。该错误主要是没有加载SQL SERVER的驱动程序。
A: 启动sqlserver2000的服务器网络实用工具后,确保Tcp/Ip协议已启动,默认的应该都启动了,这是进行通讯的条件,再选中Tcp/Ip协议后点击属性,就看到了一个默认端口号,这就是你在 getConnection里用到的端口号,必须把程序里用到的端口号,写成这里的值。
Q: 连接SQL SERVER正常,但连接后不能使用或提示SQL错误。
A: 该问题主要原因可能是没有给这个用户分配足够的权限,或者你的SQL语句中用到了SQL SERVER里保留的关键字。
Q: 错误:java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC]Can't start a cloned connection while in manual transaction mode.
A: 这个错误产生的原因一般是当你在一个SQL SERVER的JDBC连接上执行多个STATEMENTS的操作,或者是手动事务状态(AutoCommit=false) 并且使用 direct (SelectMethod=direct) 模式. Direct 模式是默认的模式.
解决办法
当你使用手动事务模式时,必须把SelectMethod 属性的值设置为 Cursor(SelectMethod= Cursor), 或者是确保在你的连接上只有一个STATEMENT操作。
1.2.4 XA-DRIVER与普通DRVIER的区别
Q:XA的Driver和普通的Driver有什么区别呢?
A:XA的Driver支持分布式的事务处理,这是与non xa driver的最大区别;JDBC2.0规范提供了进行分布式事务的能力。分布式事务是个单独的事务,可以应用在位于分离服务器上的多个异构数据库。为了支持分布式事务,JDBC2.0提供了两个新的接口: javax.sql.XADataSource和javax.sql.XAConnection。从性能的考虑来说,使用XA的DRIVER会比普通的DRIVER慢。
Q:XA的连接池,选择了支持本地事务后,是否还支持对全局的操作?
A:8.1既支持TX,也支持Non-Tx的,Weblogic对所有的已知数据库进行了包装(Wrapper),使接口一致,然而对不同的数据库,根据选择的驱动程序不同,都作了相应的优化和处理。建立数据源时,如果选择Non-Tx类型,那么它参与到JTA事务中也不会出错,因为Weblogic会启动本地事务,但是前提是必须有一个资源(XAResource)参与到事务中(多个资源的话必须打开模拟两阶段提交协议,不然会出错),但是选择Tx类型的就必须有一个全局事务,除非选择支持本地事务(SupportsLocalTransaction=true)。另外如果使用了本地事务,就必须设置autocommit为true,或者手工commit/rollback。
1.3配置连接池连接Oarcle RAC集群。
前提条件必须使用WebLogic Server version 8.1SP3 或者是更新的版本。
更详细的内容请查看
http://e-docs.bea.com/wls/docs81/jdbc/oracle_rac.html
2 JDBC连接池使用 2.1数据库连接方法总结 数据库名称
连接串
MySQL
Class.forName("org.gjt.mm.mysql.Driver"); DriverManager.getConnection( "jdbc:mysql://MyDbComputerNameOrIP:3306/myDatabaseName", sUsr, sPwd );
PostgreSQL
Class.forName("org.postgresql.Driver");
DriverManager.getConnection("jdbc:postgresql://MyDbComputerNameOrIP/myDatabaseName", sUsr, sPwd );
Oracle
Class.forName( "oracle.jdbc.driver.OracleDriver" );
DriverManager.getConnection( "jdbc:oracle:thin:@MyDbComputerNameOrIP:1521:ORCL", sUsr, sPwd );
Sybase
Class.forName("com.sybase.jdbc2.jdbc.SybDriver"); DriverManager.getConnection( "jdbc:sybase:Tds:MyDbComputerNameOrIP:2638", sUsr, sPwd );
//(Default-Username/Password: "dba"/"sql")
SQLServer
Class.forName( "net.sourceforge.jtds.jdbc.Driver" );
DriverManager.getConnection( "jdbc:jtds:sqlserver://MyDbComputerNameOrIP:1433/master", sUsr, sPwd );
ODBC
Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );
DriverManager.getConnection( "jdbc:odbc:" + sDsn, sUsr, sPwd );
DB2
Class.forName("com.ibm.db2.jdbc.net.DB2Driver");
DriverManager.getConnection("jdbc:db2://192.9.200.108:6789/SAMPLE", sUsr, sPwd );
SAP DB
Class.forName ("com.sap.dbtech.jdbc.DriverSapDB");
DriverManager.getConnection ( "jdbc:sapdb://" + host + "/" + database_name,user_name, password)
InterBase
Class.forName("interbase.interclient.Driver");
DriverManager.getConnection("jdbc:interbase://localhost/e:/testbed/database/employee.gdb", "sysdba", "masterkey" );
Microsoft SQL Server series (6.5, 7.x and 2000) and Sybase 10
JDBC Name: jTDS
Class.forName("net.sourceforge.jtds.jdbc.Driver ");
DriverManager.getConnection("jdbc:jtds:sqlserver://host:port/database","user","password");or
DriverManager.getConnection("jdbc:jtds:sybase://host:port/database","user","password");
IBM AS400
有装V4R4以上版本的Client Access Express可以在C:\Program Files\IBM\Client Access\jt400\lib找到 driver 档案 jt400.zip,并更改扩展名成为 jt400.jar语法
java.sql.DriverManager.registerDriver (new com.ibm.as400.access.AS400JDBCDriver ());
Class.forName("com.ibm.as400.access.AS400JDBCConnection");con = DriverManager.getConnection("jdbc:as400://IP","user","password");
Informix
Class.forName("com.informix.jdbc.IfxDriver").newInstance();
String url = "jdbc:informix-sqli://123.45.67.89:1533/testDB:INFORMIXSERVER=myserver; user=testuser;password=testpassword";
2.2数据库连接池使用常见问题 2.2.1连接泄漏(pool connection leak)
造成的原因一般是在使用连接后没有正确的释放连接,或者是释放的过程中出了错误。
【解决办法】
Connection leak是一件令人头痛的而又常见的错误,所以BEA提供了两种方式来解决他。首先,通过GC。那些没有被正常关闭的connection如果满足可爱的JVM GC的条件,GC会调用Connection的finalize()方法。而从connection pool中获取的connection是BEA包装过的。所以WebLogic会妥善处理这些“孤儿”connection。通过GC进行connection回收是一种很被动的做法。BEA在WLS 8.1中主动出击。通过设置weblogic-ra.xml中的inactive-connection-timeout-seconds,BEA会根据设置,主动关闭那些超时idle的connection。这就需要WLS对以分配出的connection进行周期性的检测,来看其是否活动和是否超时。
关于weblogic-ra.xm的文档如下:
http://e-docs.bea.com/wls/docs81/jconnector/dtdappen.html#1031211
早在WLS 6.1,BEA就已经在考虑自动回收“孤儿”connection了,这从JDBCConnectionPoolRuntimeMBean的getLeakedConnectionCount()方法中可见端倪。在WLS 7.0,8.1中的JDBCConnectionPoolRuntimeMBean中getLeakedConnectionCount一直存在。在8.1中,增加了通过设置idle connection的timeout时间主动关闭connection的方式,手段越来越完全了。
关于JDBCConnectionPoolRuntimeMBean的详细情况可以参见以下链接:http://e-docs.bea.com/wls/docs61/javadocs/weblogic/management/runtime/JDBCConnectionPoolRuntimeMBean.html
http://e-docs.bea.com/wls/docs70/javadocs/weblogic/management/runtime/JDBCConnectionPoolRuntimeMBean.html
http://e-docs.bea.com/wls/docs70/isv/mbeans.html
http://e-docs.bea.com/wls/docs81/javadocs/weblogic/management/runtime/JDBCConnectionPoolRuntimeMBean.html
http://e-docs.bea.com/wls/docs81/jdbc/programming.html
在Dev2Dev的Code library中已经有了一个例子,通过监听JDBCConnectionPoolRuntimeMBean的LeakedConnectionCount属性,如若其超过一设定值,会发出提醒。
http://dev2dev.bea.com/codelibrary/code/jdbc_monitor.jsp
在WLS 7.0中已经可以通过GC收leaked connection了,不过JDBCConnectionPoolRuntimeMBean的getLeakedConnectionCount好像没跟上.
2.2.2处理ORACLE的BLOB字段
1、在SQL3中,定义了一些新的数据类型,包括:
BLOB――二进制大对象,对应java.sql.Blob类型。
CLOB――字符大对象,对应java.sql.Clob类型。
ARRARY――可以存储多个某特定类型的值,对应java.sql.Array类型。
STRUCT――这是任何SQL机构类型的缺省映射,对应java.sql.Struct类型。
REF――作为数据库中SQL数据的引用,可作为参数传入SQL语句,对应java.sql.Ref类型。
2、java.sql.Blob和java.sql.Clob接口使你能够只把列值加载到内存中。getBlob()和setBlob()、getClob()和setClob(),允许程序员访问SQL BLOB和CLOB数据类型。BLOB包含了一个指向该数据的逻辑指针,而不含数据本身。使用get或set方法是只返回了一个指向该值得指针,应用程序可以读取所需的一些或全部数据。用weblogic.jdbc.vendor.oracle.OracleThinBlob对象替代oracle.sql.BLOB应该直接读取binayStream,如果采用OCI方式,即ORACLE本身的API连结,可以用读取一个Blob对象,然后转换成输出流,而如果用thin,即通用的JDBC,应该用标准的getBinayStream方法直接读取.是的,如果用thin,必须直接用jdbc,关键是把java.sql.ResultSet换成oracle.jdbc.driver.OracleResultSet,java.sql.Blob换成oracle.sql.BLOB 。
物理连接就是驱动程序中的实现java.sql.Connection的对象,逻辑连接就是一个Wraper,它实现Connection接口,并包含一个物理连接的应用,这采用装饰器设计模式,用户得到的不是物理连接,而是得到ConnectionWraper,至于close()问题,那就稍微难一点,它改变一个标志位,同时加在PooledConneciton上的ConnectionListener
ORACLE BLOB字段的处理代码见附录代码3(来自BEA网站的例子代码)
2.2.3配置连接池成功程序使用出问题
常见的主要原因是JNDI的名称写错
错误的调用代码:
public static java.sql.Connection getConnection () throws java.sql.SQLException {
java.sql.Connection conn = null;
try {
Context ictx = new InitialContext();
Context ctx = (Context) ictx.lookup("java:comp/env");//这段代码,很多资料介绍里都是这么写的
javax.sql.DataSource ds = (javax.sql.DataSource) ctx.lookup (DATA_SOURCE);
conn = ds.getConnection();
} catch (Exception e) {
Debug.printErr (e.getMessage ());
throw new SQLException ("Cannot get connection!" + e.getMessage ());
}
if (conn == null) throw new SQLException ("Cannot get connection!");
return conn;
}
正确的应该为:
Context ictx = new InitialContext();
javax.sql.DataSource ds = (javax.sql.DataSource) ictx.lookup (DATA_SOURCE);
conn = ds.getConnection();
3事务处理
该部分内容在论坛中占的不多,而且很多问题提的问题都比较模糊,回答的内容就没有一个比较明确或者是正确的解答,现针对论坛内的问题,把WEBLOGIC处理事务的一些基本概念作个介绍。
3.1事务的属性和基本概念
Required:
如果在一个事务中调用,就把该方法加到此事务中来,如果还没有启动事务,就启动一个新事务
RequiredNew:
不管当前有没有事务,都会启动一个新事务,如果当前有事务,会被挂起直到方法结束
NotSupported:
不能在事务中执行此方法。如果有事务,将会被挂起直到方法结束
Supports:
如果当前有事务,此方法会加到当前事务,如果没有,容器也不会启动新事务
Mandatory:
必须在事务中调用此方法,否则抛出异常:TransactionRequiredException
Never:
必须不在事务中调用此方法,否则抛出RemoteException(远程调用)或EJBException(本地调用)
3.1.1 Local transaction和Distributed transaction有什么区别?
Q:是不是在一个java VM上的就是local否则就是distributed?
A:Local transaction一般指的是单数据源参与的事务。 distributed transaction指的多数据源(db)参与的事务.。比如从db2中转账到oracle中.不是在一个java VM上的就是local否则就是distributed?是不是在一个jvm中不是区分local和distribute transaction的区别。注意上面的概念就应该知道了。
Q:是否可以在分布事务中使用non-XA DRIVER?
A:如果在分布事务系统中只有一个non-XA DRIVER的连接池,可以通过配置一个XA 的DATASOURCE来支持。
Q:是否可以在分布事务中使用超过一个的non-XA DRIVER的连接池?
A:不可以。如果这么使用了,当你试图从第二个non-XA connection pool中获取连接,会报如下的一个错误:
"java.sql.SQLException: Connection has already been created in this tx context for pool named <first pool's name>. Illegal attempt to create connection from another pool: <second pool's name>"
3.1.2跨资源的Transaction如何控制?
Q:如在transaction中用到JMS,又用到JDBC:在修改数据库后发送JMS消息,看文档说只能用JTS 的UserTransaction来实现,也就是说只能由开发者自己手动来管理事务,而不能用容器管理事务,是吗?
A:对于JMS来说是的.ejb本身的事务就是依靠jta来支持的,容器管理事务本质上和自己管理事务是一样的,只不过是容易提供的是一种申明性事务,不需要我们手工管理事务.
3.1.3 XA的driver,是否也是一种distribued transaction?
Q:资料上讲distributed transaction只能用JTA 的XAResource来控制事务,如JMS要参加分布式事务的话就必须用XA的。但是,我记得在我们的应用中如果在一个容器管理的事务中修改两个不同的数据库(这两个库在一台机器的同一个实例中),那么必须用XA的driver,难道这也是一种distribued transaction吗?(它们是同一种资源,都是JDBC,只是跨库而已,为什么属于分布式事务呢?)
A: 分布式事务分事务管理器,资源管理器,应用程序,以及底层事务通讯管理.在xa中一个db就是一个资源.一个jms也可以看作是一个资源,事务管理器就是协调这些资源进行统一commit或者rollback的,所以来说跨库就属于分布式事务了。
3.1.4 JTA和JTS 到底有什么区别?
JTA是进行事务调用的API, JTS则是事务的具体实现,实现事务管理,资源管理,以及底层事务通讯管理。
3.1.5 分布式事务提交或回滚后能够否关闭连接?
在事务完成后可以关闭连接。
关于事务更多的内容请参看
http://e-docs.bea.com/wls/docs60/faq/transactions.html
4论坛常见问题
1到3章的内容是针对论坛的常见问题的基本概念说明,很多问题都是由于对概念不了解造成的,希望1-3章的内容能对该论坛内的大部分问题解决有所帮助。
本章开始的内容为论坛内常见问题的解决办法,问题与回答全部来之于论坛,这里只是做了一个格式与内容的整理。
4.1 DriverManger的性能和DataSource的区别?
DriverManger直接获取的是物理的连接,通过Datasource获得链接是已经存在的物理连接,通过DriverManger直接获取数据库链接耗费的时间比通过DataSource获得耗费的时间要长。
DriverManager是管理底层jdbc的API,是java最初提供的jdbc api。java2以后都推荐使用Datasource了。另外,Datasource提供更高层的接口,这个接口的实现可以是一个链接池。而DriverManager做不到这一点。
4.2 PreparedStatement和Statement的区别在什么地方?
preparedStatement 在大批量的操作数据库的时候可以大大的提高效率,是一种预编译的方法, preparedStatement 第一次执行确实比较慢,对于只执行一次的SQL语句选择Statement是最好的. 相反, 如果SQL语句被多次执行选用PreparedStatement是最好的. 使用prepared的方式来执行一个查询. JDBC驱动会发送一个网络请求到数据解析和优化这个查询. 而执行时会产生另一个网络请求. 对于Statement, 同一个查询只会产生一次网络到数据库的通讯. 一班来说preparedStatement性能好于Statement.
4.3解释一下connection pool 中的physical connection和 logic connection 的区别
这个问题很简单,你看看Mysql的JDBC驱动就可以了,物理连接就是驱动程序中的实现java.sql.Connection的对象,逻辑连接就是一个Wraper,它实现Connection接口,并包含一个物理连接的应用,这采用装饰器设计模式,用户得到的不是物理连接,而是得到ConnectionWraper,至于close()问题,那就稍微难一点,它改变一个标志位,同时同志加在PooledConneciton上的ConnectionListener.
4.4连接池中连接使用出错: connection reset by peer, 原因?
oracle 8和9的driver不通用,还有一种应用操作会导致这种错误:当用户做了某种操作的申请,但服务还没有响应完,此时用户又重新刷新页面再次申请。
4.5数据库链接资源该怎么优化?
在页面里要连接数据库进行查询,将取得的结果显示在页面上,在每次查询后都用close关闭了连接的。平时的显示正常,在数据库中可以监视得到,创建了一个连接后,查询完了后很快就释放了,但是在一次查询还没完时,如果在浏览器上很快的按F5刷新页面,数据库的连接会不停的增加,而原来的连接释放很慢,很快就把数据库拖死了。采用连接池也只能限制总的连接数,如果一个人很快的不停的刷新,数据库不会死了,但很快一个人就把资源用完了,应用被拖死.
解决办法:
不要把连结建在BEAN中,应该写在一个类的静态方法中,然后作为参数传过去,使每个调用的人都使用同一静态连结.在连结的BEAN中首先看那个静态的连结是否是null,如果不是,就直接引用,如果是就重新建立这个连结.
4.6如果页面没有执行到关闭连接的地方,页面被关闭,如何去释放这个建立的连接?
一个方法执行,和它是否输出没有任何关系,一个JSP/SERVLET在响应时如果要执行很长时间,而在执行过程中用户关闭了页面,这个service方法并不受影响它仍然会执行完成,只是它的输出被改道了而已,在JSP/SERVLET调用和在BEAN中调用从效果上说没有任何区别,只要放在finlly块中就一定会释放.
4.7 MutilPool是什么意思,和ConnectionPool有什么区别啊?
在单SERVER的配置中使用multipool,主要用途有两个1>高可靠性;2>负载均衡。可根据实际需求选择其一。Multipool 的高可靠性只用于数据库停止的一种情况,当数据库挂起或数据库连接用光时都不起作用。
4.8 weblogic里数据源和连接池的关系是什么?
连接池可以看作是存储一群连接对象的容器,而数据源是得到一个连接的统一接口.
4.9配置连接池连接Oarcle RAC集群
BEA官方资料:http://e-docs.bea.com/wls/docs81/jdbc/oracle_rac.html
5 附录 5.1代码1---连接池设置代码
public void deployServerDataSource(){
try {
ctx = getInitialContext();
if(ctx!=null){
this.txtareaDeployStatus.append("\r\n"+"_INFO : 连接服务器,并登陆成功");
this.txtareaDeployStatus.append("\r\n"+"_INFO : 获取管理对象");
//getting the Administration MBeanHome
mbeanHome = (MBeanHome)ctx.lookup(MBeanHome.ADMIN_JNDI_NAME);
this.txtareaDeployStatus.append("\r\n"+"_INFO : 获取Admin Server");
serverMBean = (ServerMBean)mbeanHome.getAdminMBean(serverName, "Server");
this.txtareaDeployStatus.append("\r\n"+"_INFO : 获取domain");
domainName = mbeanHome.getDomainName();
}else{
this.txtareaDeployStatus.append("\r\n"+"_INFO : 连接服务器失败,请服务器正确启动,并且登陆正确");
return;
}
}
catch (Exception ex) {
this.txtareaDeployStatus.append("\r\n"+"_ERROR: 初始化管理服务器信息失败,配置终止");
return;
}
try{
this.txtareaDeployStatus.append("\r\n"+"_INFO : 开始配置WebLogic DataSource of RiseNet");
config();
this.txtareaDeployStatus.append("\r\n"+"_INFO : 配置WebLogic DataSource of RiseNet成功 ");
JOptionPane.showMessageDialog(this, "配置WebLogic DataSource of RiseNet成功", null, JOptionPane.INFORMATION_MESSAGE);
}catch(Exception ex){
this.txtareaDeployStatus.append("\r\n"+"_ERROR: 配置WebLogic DataSource of RiseNet失败 ");
JOptionPane.showMessageDialog(this, "配置WebLogic DataSource of RiseNet失败", "错误", JOptionPane.ERROR_MESSAGE);
}
//需要在配置完以后,进行一次连接测试。
try{
javax.sql.DataSource ds = null;
ds = (javax.sql.DataSource)ctx.lookup(cpDataSourceJNDIName);
java.sql.Connection c = ds.getConnection();
c.close();
}catch(Exception ex){
this.txtareaDeployStatus.append("\r\n"+"_ERROR: 测试失败 ");
this.txtareaDeployStatus.append("\r\n"+"_ERROR: 请手动进行Apply一次,否则配置DataSource在服务器重新启动后失效 ");
JOptionPane.showMessageDialog(this, "测试失败", "错误", JOptionPane.ERROR_MESSAGE);
}
}
public void config() throws Exception{
cpPoolName = this.txtPoolName.getText();
cpDataSourceName = this.txtDataSourceName.getText();
cpDataSourceJNDIName = this.txtDataSourceJNDIName.getText();
//将原有的连接DataSource信息删除
deleteDataSource();
try {
createDataSource();
}
catch (Exception ex) {
ex.printStackTrace();
throw ex;
}
}
5.2代码2---连接池监控代码
package converse;
import javax.management.DynamicMBean;
import weblogic.management.Helper;
import weblogic.management.MBeanHome;
public class MonitorBea {
private static MonitorBea _Monitor = null;
private static MBeanHome adminHome;
public MonitorBea() {
}
//获取当前的活动连接
public static int getDBPoolCurrentCount(String s) {
try {
weblogic.management.runtime.RuntimeMBean runtimembean = adminHome.
getRuntimeMBean(s, "JDBCConnectionPoolRuntime");
return Integer.parseInt(runtimembean.getAttribute(
"ActiveConnectionsCurrentCount").toString());
}
catch (Exception exception) {
return -1;
}
}
//获取当前的FREE HEAP大小
public static int getVMHeapFreeCurrent(String s) {
try {
weblogic.management.runtime.RuntimeMBean runtimembean = adminHome.
getRuntimeMBean(s, "JVMRuntime");
return Integer.parseInt(runtimembean.getAttribute("HeapFreeCurrent").
toString());
}
catch (Exception exception) {
return -1;
}
}
//获取执行队列内总线程数和IDLE线程数
public static int getExeQueueCount(int i) {
try {
weblogic.management.runtime.RuntimeMBean runtimembean = adminHome.
getRuntimeMBean("default", "ExecuteQueueRuntime");
if (i > 0)
return Integer.parseInt(runtimembean.getAttribute(
"ServicedRequestTotalCount").toString());
else
return Integer.parseInt(runtimembean.getAttribute(
"ExecuteThreadCurrentIdleCount").toString());
}
catch (Exception exception) {
return -1;
}
}
public static boolean InitMonitor(String s, String s1, String s2) {
try {
adminHome = Helper.getAdminMBeanHome(s1, s2, s);
}
catch (Exception exception) {
return false;
}
return true;
}
}
查看的JSP页面
<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="converse.*" %>
<meta HTTP-EQUIV="REFRESH" CONTENT="15;URL=./monitor.jsp">
<HTML>
<TITLE>普通用户监控</TITLE>
<BODY BGCOLOR="#CCCCCC" TEXT="#000000">
<%
//t3://192.168.100.65:20000
String _sURL6 = "t3://192.168.100.65:20000";//IP地址和端口号
String _user6 = "weblogic";//应用服务器用户名
String _pass6 = "password";//密码
String _serverName6 = "m2";//服务名
String _dbPool6 = "10000";//连接池名称
out.println("<br><br><hr>"+_sURL6);
if (MonitorBea.InitMonitor(_sURL6,_user6,_pass6))
{
//out.println("data + \r\n" );
out.print("\tHeapFreeCurrent=" + MonitorBea.getVMHeapFreeCurrent(_serverName6)/1024/1024 + "(M)");
out.print("\toraclePool=" + MonitorBea.getDBPoolCurrentCount(_dbPool6));
out.print("\tTotalCount=" + MonitorBea.getExeQueueCount(1));
out.print("\tCurrentIdle=" + MonitorBea.getExeQueueCount(0));
}
%>
</BODY>
</HTML>
5.3代码3---存取ORACLE大字段代码
package examples.jdbc.oracle;
import java.io.ByteArrayInputStream ;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ArrayIndexOutOfBoundsException;
import java.sql.*;
import java.util.Properties;
import weblogic.jdbc.common.OracleBlob;
import weblogic.jdbc.common.OracleClob;
/**
* This example demonstrates the use of Oracle Blob and Clob datatypes. The example creates a database connection
* using the Oracle Thin driver and then creates a table with a
* BLOB column and a CLOB column. It then inserts an empty BLOB and CLOB, creates a byte array to stream and
* store as a BLOB and inserts it in the table, creates a string to store as a CLOB, and then inserts it into the table.
*/
public class OracleBlobClob {
/**
* Main method
*
* @throws Exception
*/
public static void main(String argv[]) throws Exception {
String user = "scott";
String password = "tiger";
String server = "DEMO";
try {
for (int i = 0; i < argv.length; i++)
{
if (argv[i].equals("-user")) {
i++;
user = (argv[i].equals("null") ? "" : argv[i]);
}
else if (argv[i].equals("-password")) {
i++;
password = (argv[i].equals("null") ? "" : argv[i]);
}
else if (argv[i].equals("-server")) {
i++;
server = (argv[i].equals("null") ? "" : argv[i]);
}
}
} catch(ArrayIndexOutOfBoundsException aiobe) {
System.err.println("\nUsage: java examples.jdbc.oracle.OracleBlobClob [options] \n\n" +
"where options include:\n" +
"-user <user>User name to be passed to database.\n" +
"-password <password>User password to be passed to database.\n" +
"-server <server>DNS name of database server.\n");
System.exit(1);
}
java.sql.Blob myBlob= null;
java.sql.Clob myClob= null;
Connection conn = null;
// get a connection to the Oracle DBMS
// substitute the name of the machine hosting your
// Oracle server for myOracle8Server
Properties props = new Properties();
props.put("user",user);
props.put("password", password);
props.put("server",server);
try {
Driver myDriver = (Driver)
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
conn = myDriver.connect("jdbc:oracle:thin:" , props);
// set Oracle's Auto Commit feature to false.
// This is necessary when manipulating Blobs and Clobs.
conn.setAutoCommit(false);
// ============== Create Table ==================
// Create a table with a Blob and Clob column
try {
// if table does not exist, create it.
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 created.");
// ============== Initializing blob and clob values ==================
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.");
// ============== Manipulating the Blob column ======================
// get a reference to the Blob column
stmt.execute("select * from lobtest where id=44");
ResultSet rs = stmt.getResultSet();
while ( rs.next() ) {
myBlob = rs.getBlob("blobcol");
}
// Create a byte array and store some data in it
System.out.println("\nCreating the following byte array:");
int STREAM_SIZE = 10;
byte[] b = new byte[STREAM_SIZE];
for (int i=0; i < STREAM_SIZE; i++) {
b[i] = (byte)(40 + (i%20)); // range 40-60
System.out.println("byte[" + i + "] = " + b[i]);
}
// Write the byte array to a stream and store it in the Blob column
System.out.println
("\nWriting the byte array to a stream" +
" and storing it in the table as a blob...");
InputStream is = new ByteArrayInputStream(b);
OutputStream os = ((oracle.sql.BLOB) myBlob).getBinaryOutputStream();
byte[] inBytes = new byte[STREAM_SIZE];
int numBytes = is.read(inBytes);
// write the input stream to the output stream
while (numBytes > 0) {
os.write(inBytes, 0, numBytes);
numBytes = is.read(inBytes);
}
// The flush() method causes the data to be written to the table
os.flush();
//read back the blob
System.out.println("\nReading the blob back from the table and displaying:");
Statement readblob = conn.createStatement();
readblob.execute("select * from lobtest where id=44");
ResultSet rsreadblob = readblob.getResultSet();
// read the blob into a byte array and display
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 < STREAM_SIZE ; i++) {
r[i] = (byte) readis.read();
System.out.println("output [" + i + "] = " + r[i]);
}
}
// create some character data to work with
String ss = "abcdefghijklmnopqrstuvwxyz";
System.out.println("\nCreated the following string to be stored as a clob:\n" +
ss);
// ============== Manipulating the Clob column ======================
// get a reference to the clob column
stmt.execute("select * from lobtest where id=44");
ResultSet crs = stmt.getResultSet();
while ( crs.next() ) {
myClob = crs.getClob("clobcol");
java.io.OutputStream osss =
((oracle.sql.CLOB) myClob).getAsciiOutputStream();
byte[] bss = ss.getBytes("ASCII");
osss.write(bss);
osss.flush();
}
conn.commit();
// read back the 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();
// read the clob in as and ASCII stream, write to a character array, and display
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]);
}
}
// Drop the table and clean up connections
System.out.println("\nDropping table...");
Statement dropstmt = conn.createStatement();
dropstmt.execute("drop table lobtest");
System.out.println("Table dropped.");
} catch (Exception e) {
System.out.println("Exception was thrown: " + e.getMessage());
throw e;
} finally {
try {
if (conn != null)
conn.close();
} catch (SQLException sqle) {
System.out.println("SQLException was thrown: " + sqle.getMessage());
throw sqle;
}
}
}
}
论坛内经常有人询问如何配置连接池的问题,这里把配置的详细过程都再重复一遍,并包含论坛内对配置连接池出现的问题回答进行整理。
STEP 1:数据库类型和驱动类型的选择,对于各种TYPE的驱动附录内容会做介绍。
STEP 2:连接池连接属性配置,连接URL,用户名/密码,数据库服务名。
STEP 3:测试连接池配置是否正确。
STEP 4:测试成功后进行部署。
STEP 5:部署成功,选择该连接进行连接池的参数配置。
STEP 6:连接池的参数配置。
配置完成后在config.xml 文件中对应的各属性解释如下:
Initial Capacity:创建连接池时所创建的数据库连接的数目。
Maximum Capacity: 连接池中连接的最大数目。
Capacity Increment: 连接池容量在最大容量限制范围内的增量。
LoginDelay: 在创建每个物理数据库连接之前要延迟的秒数。
Allow Shrinking: 将该项设置为true时,如果没有使用额外的连接,则允许连接池把容量减小到InitialCapacity。
Shrink Frequency: 在减小连接池容量之前要等待的秒数。如果将Shrink Frequency设置为true,那么也必须将Allow Shrinking设置为true。
Test Frequency: 数据库连接测试之间间隔的秒数。在每个Refresh Period时间间隔之后,如果设置了TestTableName,就会使用TestTableName测试未使用的数据库连接。
Test Reserved Connections: 如果选择了这个选项,服务器会在把连接提供给客户端之前对其进行测试。
Test Created Connections: 如果选择了这个选项,就会在创建一个JDBC连接之后和在把它添加到JDBC连接池中的可用连接列表之前,对该JDBC连接进行测试。
Test Released Connections: 如果选择了这个选项,服务器就会在把连接返回给连接池之前对其进行测试。
Test Table Name: 用于JDBC连接测试的数据库表名。如果指定了Test Frequency,并且选择了Test Reserved Connections、Test Created Connections或Test Released Connections,则Table Name是必需的。
Weblogic.codeset=GBK:编码格式
1.1.1 通过程序配置连接池
配置连接池可以通过weblogic.management.configuration.JDBCConnectionPoolMBean或者是weblogic.management.configuration.JDBCDataSourceMBeanl编程进行。
具体代码见附录部分—代码1(连接池设置)
1.1.2 通过程序查看连接池运行状态信息
配置连接池可以通过weblogic.management.configuration.JDBCConnectionPoolMBean或者编程获取运行态的信息。
具体代码见附录部分—代码2(连接池监控)
1.2配置连接池常见问题 1.2.1 连接有效性测试选项
Q:连接池配好后,启动正常,如果Connection Pool在使用过程中与数据库的联系因为网络的问题或别的原因断掉,是不是必须重新启动weblogic才能重新让Connection Pool连上数据库?我现在每次一碰到数据库连不上就要重启一次wlsServer,烦得要命。
此类问题出现的原因:
应用服务器到数据库端的网络连接不可靠;
数据库在系统运行的情况下重启动;
驱动程序的问题造成连接不可用。
A: WLS里设置连接的检查,一个是获取连接的时候检查该连接是否有效,另外一个就是释放连接的时候检查。这两个检查在配置连接池的时候都是可以设置的。
设置的参数说明:
参数名称
参数说明
参数选择值
TestConnectionsOnReserve
从连接池获取连接后是否进行有效性测试
True/false
RefreshMinutes parameter
设定connection pool的刷新时间
刷新的时间间隔
Test Table Name
测试的表名,也可以指定SQL
表名或者是SQL
1.2.2不同类型驱动的区别与选择
Q:请教console中连接池的oracle驱动程序那个多,用哪个好呢?他们的驱动程序文件分别对应LIB目录下的哪个文件?
A: BEA_HOME$/weblogic81/server/lib目录内,如果需要连接不同的数据库需要把对应的驱动程序置于该目录内。
JDBC驱动的类型与选择,在配置连接池的时候进行选择。
JDBC-1图JDBC-2图
【TYPE 1:JDBC-ODBC桥】
JDBC-1图左边的分支称为TYPE 1,即通常由Sun公司提供的JDBC-ODBC桥接器。它提供了经由一种或多种ODBC驱动进行访问的JDBC接口,而ODBC驱动,在很多情况下也即数据库的客户端,必须加载到客户机。因而,它适用于下载和自动安装Java程序不重要、实验用途或者没有其它JDBC驱动可用的情况下。执行效率比较低,对于那些大数据量存取的应用是不适合的.而且,这种方法要求客户端必须安装ODBC 驱动,所以对于基于 internet ,intranet的应用也是不合适的.因为,不可能要求所有客户都能找到ODBC DRIVER。
【TYPE 2:本地API驱动】
JDBC-1图右边的分支成为模式2,类似于JDBC-ODBC桥接器,需要加载到客户机,却是一个部分用Java实现的驱动接口。它将JDBC调用转换为对数据库(Oracle、Sybase、Informix、DB2等)客户端接口的调用。这种驱动比起TYPE 1执行效率大大提高了,但它仍然需要在客户端加载数据库厂商提供的代码库。这样就不适合基于internet的应用。
【TYPE 3:网络协议驱动】
JDBC-2图右边的分支称为TYPE 3,它同样是一个纯Java驱动,不同于TYPE 4的是基于网络协议。它的机制是将JDBC调用转换为中间网络协议,然后转换为DBMS协议。中间网络协议层起到一个读取数据库的中间件的作用,能够连接许多类型的数据库,因而是最灵活的JDBC模式。这种模式的产品比较适用于企业内部互联网,如若支持国际互联网,还需添加对安全、穿过防火墙访问等的支持。
【TYPE 4:本地协议驱动】
图2左边的分支称为TYPE 4,它一般是数据库厂商才能实现的纯Java的基于本地协议的驱动,直接调用DBMS(数据库管理系统)使用的网络协议,对于企业内部互联网来说,是一个实用的解决方案。
1.2.3 JDBC连SQL SERVER数据库的常见问题
使用TYPE4类驱动程序,目前支持两种版本的SQL SERVER
WebLogic jDriver for Microsoft SQL Server Version 7.0 and 2000, 这个版本的驱动是WEBLOGIC的默认设置,不需要做其他的配置。
支持SQL Server 7.0 和 2000.
支持新的数据类型SQL Server Version 7.0 and 2000.
WebLogic jDriver for Microsoft SQL Server Versions 6.5 and 7.0, 使用这个版本的驱动,必须在CLASSPATH路径里增加ssqlserver4v65.jar。
支持SQL Server 6.5.
支持SQL Server 7.0 但有以下两个限制: 一,是否按照6.5的语义规则 creates columns that do not allow null values. (This behavior is normal for SQL Server version 6.5.)。二,不支持新的 SQL Server 7.0数据类型。
知道了以上两点后,有些问题就能很明确了。
Q: ClassNotFoundException的错误。该错误主要是没有加载SQL SERVER的驱动程序。
A: JDBC连接SQL SERVER需要三个包:msutil.jar,msbase.jar,mssqlserver.jar,可以把这三个包拷贝到BEA_HOME$/weblogic81/server/lib目录内。
Q: [Microsoft][SQLServer 2000 Driver for JDBC]Error establishing socket的错误。该错误主要是没有加载SQL SERVER的驱动程序。
A: 启动sqlserver2000的服务器网络实用工具后,确保Tcp/Ip协议已启动,默认的应该都启动了,这是进行通讯的条件,再选中Tcp/Ip协议后点击属性,就看到了一个默认端口号,这就是你在 getConnection里用到的端口号,必须把程序里用到的端口号,写成这里的值。
Q: 连接SQL SERVER正常,但连接后不能使用或提示SQL错误。
A: 该问题主要原因可能是没有给这个用户分配足够的权限,或者你的SQL语句中用到了SQL SERVER里保留的关键字。
Q: 错误:java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC]Can't start a cloned connection while in manual transaction mode.
A: 这个错误产生的原因一般是当你在一个SQL SERVER的JDBC连接上执行多个STATEMENTS的操作,或者是手动事务状态(AutoCommit=false) 并且使用 direct (SelectMethod=direct) 模式. Direct 模式是默认的模式.
解决办法
当你使用手动事务模式时,必须把SelectMethod 属性的值设置为 Cursor(SelectMethod= Cursor), 或者是确保在你的连接上只有一个STATEMENT操作。
1.2.4 XA-DRIVER与普通DRVIER的区别
Q:XA的Driver和普通的Driver有什么区别呢?
A:XA的Driver支持分布式的事务处理,这是与non xa driver的最大区别;JDBC2.0规范提供了进行分布式事务的能力。分布式事务是个单独的事务,可以应用在位于分离服务器上的多个异构数据库。为了支持分布式事务,JDBC2.0提供了两个新的接口: javax.sql.XADataSource和javax.sql.XAConnection。从性能的考虑来说,使用XA的DRIVER会比普通的DRIVER慢。
Q:XA的连接池,选择了支持本地事务后,是否还支持对全局的操作?
A:8.1既支持TX,也支持Non-Tx的,Weblogic对所有的已知数据库进行了包装(Wrapper),使接口一致,然而对不同的数据库,根据选择的驱动程序不同,都作了相应的优化和处理。建立数据源时,如果选择Non-Tx类型,那么它参与到JTA事务中也不会出错,因为Weblogic会启动本地事务,但是前提是必须有一个资源(XAResource)参与到事务中(多个资源的话必须打开模拟两阶段提交协议,不然会出错),但是选择Tx类型的就必须有一个全局事务,除非选择支持本地事务(SupportsLocalTransaction=true)。另外如果使用了本地事务,就必须设置autocommit为true,或者手工commit/rollback。
1.3配置连接池连接Oarcle RAC集群。
前提条件必须使用WebLogic Server version 8.1SP3 或者是更新的版本。
更详细的内容请查看
http://e-docs.bea.com/wls/docs81/jdbc/oracle_rac.html
2 JDBC连接池使用 2.1数据库连接方法总结 数据库名称
连接串
MySQL
Class.forName("org.gjt.mm.mysql.Driver"); DriverManager.getConnection( "jdbc:mysql://MyDbComputerNameOrIP:3306/myDatabaseName", sUsr, sPwd );
PostgreSQL
Class.forName("org.postgresql.Driver");
DriverManager.getConnection("jdbc:postgresql://MyDbComputerNameOrIP/myDatabaseName", sUsr, sPwd );
Oracle
Class.forName( "oracle.jdbc.driver.OracleDriver" );
DriverManager.getConnection( "jdbc:oracle:thin:@MyDbComputerNameOrIP:1521:ORCL", sUsr, sPwd );
Sybase
Class.forName("com.sybase.jdbc2.jdbc.SybDriver"); DriverManager.getConnection( "jdbc:sybase:Tds:MyDbComputerNameOrIP:2638", sUsr, sPwd );
//(Default-Username/Password: "dba"/"sql")
SQLServer
Class.forName( "net.sourceforge.jtds.jdbc.Driver" );
DriverManager.getConnection( "jdbc:jtds:sqlserver://MyDbComputerNameOrIP:1433/master", sUsr, sPwd );
ODBC
Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );
DriverManager.getConnection( "jdbc:odbc:" + sDsn, sUsr, sPwd );
DB2
Class.forName("com.ibm.db2.jdbc.net.DB2Driver");
DriverManager.getConnection("jdbc:db2://192.9.200.108:6789/SAMPLE", sUsr, sPwd );
SAP DB
Class.forName ("com.sap.dbtech.jdbc.DriverSapDB");
DriverManager.getConnection ( "jdbc:sapdb://" + host + "/" + database_name,user_name, password)
InterBase
Class.forName("interbase.interclient.Driver");
DriverManager.getConnection("jdbc:interbase://localhost/e:/testbed/database/employee.gdb", "sysdba", "masterkey" );
Microsoft SQL Server series (6.5, 7.x and 2000) and Sybase 10
JDBC Name: jTDS
Class.forName("net.sourceforge.jtds.jdbc.Driver ");
DriverManager.getConnection("jdbc:jtds:sqlserver://host:port/database","user","password");or
DriverManager.getConnection("jdbc:jtds:sybase://host:port/database","user","password");
IBM AS400
有装V4R4以上版本的Client Access Express可以在C:\Program Files\IBM\Client Access\jt400\lib找到 driver 档案 jt400.zip,并更改扩展名成为 jt400.jar语法
java.sql.DriverManager.registerDriver (new com.ibm.as400.access.AS400JDBCDriver ());
Class.forName("com.ibm.as400.access.AS400JDBCConnection");con = DriverManager.getConnection("jdbc:as400://IP","user","password");
Informix
Class.forName("com.informix.jdbc.IfxDriver").newInstance();
String url = "jdbc:informix-sqli://123.45.67.89:1533/testDB:INFORMIXSERVER=myserver; user=testuser;password=testpassword";
2.2数据库连接池使用常见问题 2.2.1连接泄漏(pool connection leak)
造成的原因一般是在使用连接后没有正确的释放连接,或者是释放的过程中出了错误。
【解决办法】
Connection leak是一件令人头痛的而又常见的错误,所以BEA提供了两种方式来解决他。首先,通过GC。那些没有被正常关闭的connection如果满足可爱的JVM GC的条件,GC会调用Connection的finalize()方法。而从connection pool中获取的connection是BEA包装过的。所以WebLogic会妥善处理这些“孤儿”connection。通过GC进行connection回收是一种很被动的做法。BEA在WLS 8.1中主动出击。通过设置weblogic-ra.xml中的inactive-connection-timeout-seconds,BEA会根据设置,主动关闭那些超时idle的connection。这就需要WLS对以分配出的connection进行周期性的检测,来看其是否活动和是否超时。
关于weblogic-ra.xm的文档如下:
http://e-docs.bea.com/wls/docs81/jconnector/dtdappen.html#1031211
早在WLS 6.1,BEA就已经在考虑自动回收“孤儿”connection了,这从JDBCConnectionPoolRuntimeMBean的getLeakedConnectionCount()方法中可见端倪。在WLS 7.0,8.1中的JDBCConnectionPoolRuntimeMBean中getLeakedConnectionCount一直存在。在8.1中,增加了通过设置idle connection的timeout时间主动关闭connection的方式,手段越来越完全了。
关于JDBCConnectionPoolRuntimeMBean的详细情况可以参见以下链接:http://e-docs.bea.com/wls/docs61/javadocs/weblogic/management/runtime/JDBCConnectionPoolRuntimeMBean.html
http://e-docs.bea.com/wls/docs70/javadocs/weblogic/management/runtime/JDBCConnectionPoolRuntimeMBean.html
http://e-docs.bea.com/wls/docs70/isv/mbeans.html
http://e-docs.bea.com/wls/docs81/javadocs/weblogic/management/runtime/JDBCConnectionPoolRuntimeMBean.html
http://e-docs.bea.com/wls/docs81/jdbc/programming.html
在Dev2Dev的Code library中已经有了一个例子,通过监听JDBCConnectionPoolRuntimeMBean的LeakedConnectionCount属性,如若其超过一设定值,会发出提醒。
http://dev2dev.bea.com/codelibrary/code/jdbc_monitor.jsp
在WLS 7.0中已经可以通过GC收leaked connection了,不过JDBCConnectionPoolRuntimeMBean的getLeakedConnectionCount好像没跟上.
2.2.2处理ORACLE的BLOB字段
1、在SQL3中,定义了一些新的数据类型,包括:
BLOB――二进制大对象,对应java.sql.Blob类型。
CLOB――字符大对象,对应java.sql.Clob类型。
ARRARY――可以存储多个某特定类型的值,对应java.sql.Array类型。
STRUCT――这是任何SQL机构类型的缺省映射,对应java.sql.Struct类型。
REF――作为数据库中SQL数据的引用,可作为参数传入SQL语句,对应java.sql.Ref类型。
2、java.sql.Blob和java.sql.Clob接口使你能够只把列值加载到内存中。getBlob()和setBlob()、getClob()和setClob(),允许程序员访问SQL BLOB和CLOB数据类型。BLOB包含了一个指向该数据的逻辑指针,而不含数据本身。使用get或set方法是只返回了一个指向该值得指针,应用程序可以读取所需的一些或全部数据。用weblogic.jdbc.vendor.oracle.OracleThinBlob对象替代oracle.sql.BLOB应该直接读取binayStream,如果采用OCI方式,即ORACLE本身的API连结,可以用读取一个Blob对象,然后转换成输出流,而如果用thin,即通用的JDBC,应该用标准的getBinayStream方法直接读取.是的,如果用thin,必须直接用jdbc,关键是把java.sql.ResultSet换成oracle.jdbc.driver.OracleResultSet,java.sql.Blob换成oracle.sql.BLOB 。
物理连接就是驱动程序中的实现java.sql.Connection的对象,逻辑连接就是一个Wraper,它实现Connection接口,并包含一个物理连接的应用,这采用装饰器设计模式,用户得到的不是物理连接,而是得到ConnectionWraper,至于close()问题,那就稍微难一点,它改变一个标志位,同时加在PooledConneciton上的ConnectionListener
ORACLE BLOB字段的处理代码见附录代码3(来自BEA网站的例子代码)
2.2.3配置连接池成功程序使用出问题
常见的主要原因是JNDI的名称写错
错误的调用代码:
public static java.sql.Connection getConnection () throws java.sql.SQLException {
java.sql.Connection conn = null;
try {
Context ictx = new InitialContext();
Context ctx = (Context) ictx.lookup("java:comp/env");//这段代码,很多资料介绍里都是这么写的
javax.sql.DataSource ds = (javax.sql.DataSource) ctx.lookup (DATA_SOURCE);
conn = ds.getConnection();
} catch (Exception e) {
Debug.printErr (e.getMessage ());
throw new SQLException ("Cannot get connection!" + e.getMessage ());
}
if (conn == null) throw new SQLException ("Cannot get connection!");
return conn;
}
正确的应该为:
Context ictx = new InitialContext();
javax.sql.DataSource ds = (javax.sql.DataSource) ictx.lookup (DATA_SOURCE);
conn = ds.getConnection();
3事务处理
该部分内容在论坛中占的不多,而且很多问题提的问题都比较模糊,回答的内容就没有一个比较明确或者是正确的解答,现针对论坛内的问题,把WEBLOGIC处理事务的一些基本概念作个介绍。
3.1事务的属性和基本概念
Required:
如果在一个事务中调用,就把该方法加到此事务中来,如果还没有启动事务,就启动一个新事务
RequiredNew:
不管当前有没有事务,都会启动一个新事务,如果当前有事务,会被挂起直到方法结束
NotSupported:
不能在事务中执行此方法。如果有事务,将会被挂起直到方法结束
Supports:
如果当前有事务,此方法会加到当前事务,如果没有,容器也不会启动新事务
Mandatory:
必须在事务中调用此方法,否则抛出异常:TransactionRequiredException
Never:
必须不在事务中调用此方法,否则抛出RemoteException(远程调用)或EJBException(本地调用)
3.1.1 Local transaction和Distributed transaction有什么区别?
Q:是不是在一个java VM上的就是local否则就是distributed?
A:Local transaction一般指的是单数据源参与的事务。 distributed transaction指的多数据源(db)参与的事务.。比如从db2中转账到oracle中.不是在一个java VM上的就是local否则就是distributed?是不是在一个jvm中不是区分local和distribute transaction的区别。注意上面的概念就应该知道了。
Q:是否可以在分布事务中使用non-XA DRIVER?
A:如果在分布事务系统中只有一个non-XA DRIVER的连接池,可以通过配置一个XA 的DATASOURCE来支持。
Q:是否可以在分布事务中使用超过一个的non-XA DRIVER的连接池?
A:不可以。如果这么使用了,当你试图从第二个non-XA connection pool中获取连接,会报如下的一个错误:
"java.sql.SQLException: Connection has already been created in this tx context for pool named <first pool's name>. Illegal attempt to create connection from another pool: <second pool's name>"
3.1.2跨资源的Transaction如何控制?
Q:如在transaction中用到JMS,又用到JDBC:在修改数据库后发送JMS消息,看文档说只能用JTS 的UserTransaction来实现,也就是说只能由开发者自己手动来管理事务,而不能用容器管理事务,是吗?
A:对于JMS来说是的.ejb本身的事务就是依靠jta来支持的,容器管理事务本质上和自己管理事务是一样的,只不过是容易提供的是一种申明性事务,不需要我们手工管理事务.
3.1.3 XA的driver,是否也是一种distribued transaction?
Q:资料上讲distributed transaction只能用JTA 的XAResource来控制事务,如JMS要参加分布式事务的话就必须用XA的。但是,我记得在我们的应用中如果在一个容器管理的事务中修改两个不同的数据库(这两个库在一台机器的同一个实例中),那么必须用XA的driver,难道这也是一种distribued transaction吗?(它们是同一种资源,都是JDBC,只是跨库而已,为什么属于分布式事务呢?)
A: 分布式事务分事务管理器,资源管理器,应用程序,以及底层事务通讯管理.在xa中一个db就是一个资源.一个jms也可以看作是一个资源,事务管理器就是协调这些资源进行统一commit或者rollback的,所以来说跨库就属于分布式事务了。
3.1.4 JTA和JTS 到底有什么区别?
JTA是进行事务调用的API, JTS则是事务的具体实现,实现事务管理,资源管理,以及底层事务通讯管理。
3.1.5 分布式事务提交或回滚后能够否关闭连接?
在事务完成后可以关闭连接。
关于事务更多的内容请参看
http://e-docs.bea.com/wls/docs60/faq/transactions.html
4论坛常见问题
1到3章的内容是针对论坛的常见问题的基本概念说明,很多问题都是由于对概念不了解造成的,希望1-3章的内容能对该论坛内的大部分问题解决有所帮助。
本章开始的内容为论坛内常见问题的解决办法,问题与回答全部来之于论坛,这里只是做了一个格式与内容的整理。
4.1 DriverManger的性能和DataSource的区别?
DriverManger直接获取的是物理的连接,通过Datasource获得链接是已经存在的物理连接,通过DriverManger直接获取数据库链接耗费的时间比通过DataSource获得耗费的时间要长。
DriverManager是管理底层jdbc的API,是java最初提供的jdbc api。java2以后都推荐使用Datasource了。另外,Datasource提供更高层的接口,这个接口的实现可以是一个链接池。而DriverManager做不到这一点。
4.2 PreparedStatement和Statement的区别在什么地方?
preparedStatement 在大批量的操作数据库的时候可以大大的提高效率,是一种预编译的方法, preparedStatement 第一次执行确实比较慢,对于只执行一次的SQL语句选择Statement是最好的. 相反, 如果SQL语句被多次执行选用PreparedStatement是最好的. 使用prepared的方式来执行一个查询. JDBC驱动会发送一个网络请求到数据解析和优化这个查询. 而执行时会产生另一个网络请求. 对于Statement, 同一个查询只会产生一次网络到数据库的通讯. 一班来说preparedStatement性能好于Statement.
4.3解释一下connection pool 中的physical connection和 logic connection 的区别
这个问题很简单,你看看Mysql的JDBC驱动就可以了,物理连接就是驱动程序中的实现java.sql.Connection的对象,逻辑连接就是一个Wraper,它实现Connection接口,并包含一个物理连接的应用,这采用装饰器设计模式,用户得到的不是物理连接,而是得到ConnectionWraper,至于close()问题,那就稍微难一点,它改变一个标志位,同时同志加在PooledConneciton上的ConnectionListener.
4.4连接池中连接使用出错: connection reset by peer, 原因?
oracle 8和9的driver不通用,还有一种应用操作会导致这种错误:当用户做了某种操作的申请,但服务还没有响应完,此时用户又重新刷新页面再次申请。
4.5数据库链接资源该怎么优化?
在页面里要连接数据库进行查询,将取得的结果显示在页面上,在每次查询后都用close关闭了连接的。平时的显示正常,在数据库中可以监视得到,创建了一个连接后,查询完了后很快就释放了,但是在一次查询还没完时,如果在浏览器上很快的按F5刷新页面,数据库的连接会不停的增加,而原来的连接释放很慢,很快就把数据库拖死了。采用连接池也只能限制总的连接数,如果一个人很快的不停的刷新,数据库不会死了,但很快一个人就把资源用完了,应用被拖死.
解决办法:
不要把连结建在BEAN中,应该写在一个类的静态方法中,然后作为参数传过去,使每个调用的人都使用同一静态连结.在连结的BEAN中首先看那个静态的连结是否是null,如果不是,就直接引用,如果是就重新建立这个连结.
4.6如果页面没有执行到关闭连接的地方,页面被关闭,如何去释放这个建立的连接?
一个方法执行,和它是否输出没有任何关系,一个JSP/SERVLET在响应时如果要执行很长时间,而在执行过程中用户关闭了页面,这个service方法并不受影响它仍然会执行完成,只是它的输出被改道了而已,在JSP/SERVLET调用和在BEAN中调用从效果上说没有任何区别,只要放在finlly块中就一定会释放.
4.7 MutilPool是什么意思,和ConnectionPool有什么区别啊?
在单SERVER的配置中使用multipool,主要用途有两个1>高可靠性;2>负载均衡。可根据实际需求选择其一。Multipool 的高可靠性只用于数据库停止的一种情况,当数据库挂起或数据库连接用光时都不起作用。
4.8 weblogic里数据源和连接池的关系是什么?
连接池可以看作是存储一群连接对象的容器,而数据源是得到一个连接的统一接口.
4.9配置连接池连接Oarcle RAC集群
BEA官方资料:http://e-docs.bea.com/wls/docs81/jdbc/oracle_rac.html
5 附录 5.1代码1---连接池设置代码
public void deployServerDataSource(){
try {
ctx = getInitialContext();
if(ctx!=null){
this.txtareaDeployStatus.append("\r\n"+"_INFO : 连接服务器,并登陆成功");
this.txtareaDeployStatus.append("\r\n"+"_INFO : 获取管理对象");
//getting the Administration MBeanHome
mbeanHome = (MBeanHome)ctx.lookup(MBeanHome.ADMIN_JNDI_NAME);
this.txtareaDeployStatus.append("\r\n"+"_INFO : 获取Admin Server");
serverMBean = (ServerMBean)mbeanHome.getAdminMBean(serverName, "Server");
this.txtareaDeployStatus.append("\r\n"+"_INFO : 获取domain");
domainName = mbeanHome.getDomainName();
}else{
this.txtareaDeployStatus.append("\r\n"+"_INFO : 连接服务器失败,请服务器正确启动,并且登陆正确");
return;
}
}
catch (Exception ex) {
this.txtareaDeployStatus.append("\r\n"+"_ERROR: 初始化管理服务器信息失败,配置终止");
return;
}
try{
this.txtareaDeployStatus.append("\r\n"+"_INFO : 开始配置WebLogic DataSource of RiseNet");
config();
this.txtareaDeployStatus.append("\r\n"+"_INFO : 配置WebLogic DataSource of RiseNet成功 ");
JOptionPane.showMessageDialog(this, "配置WebLogic DataSource of RiseNet成功", null, JOptionPane.INFORMATION_MESSAGE);
}catch(Exception ex){
this.txtareaDeployStatus.append("\r\n"+"_ERROR: 配置WebLogic DataSource of RiseNet失败 ");
JOptionPane.showMessageDialog(this, "配置WebLogic DataSource of RiseNet失败", "错误", JOptionPane.ERROR_MESSAGE);
}
//需要在配置完以后,进行一次连接测试。
try{
javax.sql.DataSource ds = null;
ds = (javax.sql.DataSource)ctx.lookup(cpDataSourceJNDIName);
java.sql.Connection c = ds.getConnection();
c.close();
}catch(Exception ex){
this.txtareaDeployStatus.append("\r\n"+"_ERROR: 测试失败 ");
this.txtareaDeployStatus.append("\r\n"+"_ERROR: 请手动进行Apply一次,否则配置DataSource在服务器重新启动后失效 ");
JOptionPane.showMessageDialog(this, "测试失败", "错误", JOptionPane.ERROR_MESSAGE);
}
}
public void config() throws Exception{
cpPoolName = this.txtPoolName.getText();
cpDataSourceName = this.txtDataSourceName.getText();
cpDataSourceJNDIName = this.txtDataSourceJNDIName.getText();
//将原有的连接DataSource信息删除
deleteDataSource();
try {
createDataSource();
}
catch (Exception ex) {
ex.printStackTrace();
throw ex;
}
}
5.2代码2---连接池监控代码
package converse;
import javax.management.DynamicMBean;
import weblogic.management.Helper;
import weblogic.management.MBeanHome;
public class MonitorBea {
private static MonitorBea _Monitor = null;
private static MBeanHome adminHome;
public MonitorBea() {
}
//获取当前的活动连接
public static int getDBPoolCurrentCount(String s) {
try {
weblogic.management.runtime.RuntimeMBean runtimembean = adminHome.
getRuntimeMBean(s, "JDBCConnectionPoolRuntime");
return Integer.parseInt(runtimembean.getAttribute(
"ActiveConnectionsCurrentCount").toString());
}
catch (Exception exception) {
return -1;
}
}
//获取当前的FREE HEAP大小
public static int getVMHeapFreeCurrent(String s) {
try {
weblogic.management.runtime.RuntimeMBean runtimembean = adminHome.
getRuntimeMBean(s, "JVMRuntime");
return Integer.parseInt(runtimembean.getAttribute("HeapFreeCurrent").
toString());
}
catch (Exception exception) {
return -1;
}
}
//获取执行队列内总线程数和IDLE线程数
public static int getExeQueueCount(int i) {
try {
weblogic.management.runtime.RuntimeMBean runtimembean = adminHome.
getRuntimeMBean("default", "ExecuteQueueRuntime");
if (i > 0)
return Integer.parseInt(runtimembean.getAttribute(
"ServicedRequestTotalCount").toString());
else
return Integer.parseInt(runtimembean.getAttribute(
"ExecuteThreadCurrentIdleCount").toString());
}
catch (Exception exception) {
return -1;
}
}
public static boolean InitMonitor(String s, String s1, String s2) {
try {
adminHome = Helper.getAdminMBeanHome(s1, s2, s);
}
catch (Exception exception) {
return false;
}
return true;
}
}
查看的JSP页面
<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="converse.*" %>
<meta HTTP-EQUIV="REFRESH" CONTENT="15;URL=./monitor.jsp">
<HTML>
<TITLE>普通用户监控</TITLE>
<BODY BGCOLOR="#CCCCCC" TEXT="#000000">
<%
//t3://192.168.100.65:20000
String _sURL6 = "t3://192.168.100.65:20000";//IP地址和端口号
String _user6 = "weblogic";//应用服务器用户名
String _pass6 = "password";//密码
String _serverName6 = "m2";//服务名
String _dbPool6 = "10000";//连接池名称
out.println("<br><br><hr>"+_sURL6);
if (MonitorBea.InitMonitor(_sURL6,_user6,_pass6))
{
//out.println("data + \r\n" );
out.print("\tHeapFreeCurrent=" + MonitorBea.getVMHeapFreeCurrent(_serverName6)/1024/1024 + "(M)");
out.print("\toraclePool=" + MonitorBea.getDBPoolCurrentCount(_dbPool6));
out.print("\tTotalCount=" + MonitorBea.getExeQueueCount(1));
out.print("\tCurrentIdle=" + MonitorBea.getExeQueueCount(0));
}
%>
</BODY>
</HTML>
5.3代码3---存取ORACLE大字段代码
package examples.jdbc.oracle;
import java.io.ByteArrayInputStream ;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ArrayIndexOutOfBoundsException;
import java.sql.*;
import java.util.Properties;
import weblogic.jdbc.common.OracleBlob;
import weblogic.jdbc.common.OracleClob;
/**
* This example demonstrates the use of Oracle Blob and Clob datatypes. The example creates a database connection
* using the Oracle Thin driver and then creates a table with a
* BLOB column and a CLOB column. It then inserts an empty BLOB and CLOB, creates a byte array to stream and
* store as a BLOB and inserts it in the table, creates a string to store as a CLOB, and then inserts it into the table.
*/
public class OracleBlobClob {
/**
* Main method
*
* @throws Exception
*/
public static void main(String argv[]) throws Exception {
String user = "scott";
String password = "tiger";
String server = "DEMO";
try {
for (int i = 0; i < argv.length; i++)
{
if (argv[i].equals("-user")) {
i++;
user = (argv[i].equals("null") ? "" : argv[i]);
}
else if (argv[i].equals("-password")) {
i++;
password = (argv[i].equals("null") ? "" : argv[i]);
}
else if (argv[i].equals("-server")) {
i++;
server = (argv[i].equals("null") ? "" : argv[i]);
}
}
} catch(ArrayIndexOutOfBoundsException aiobe) {
System.err.println("\nUsage: java examples.jdbc.oracle.OracleBlobClob [options] \n\n" +
"where options include:\n" +
"-user <user>User name to be passed to database.\n" +
"-password <password>User password to be passed to database.\n" +
"-server <server>DNS name of database server.\n");
System.exit(1);
}
java.sql.Blob myBlob= null;
java.sql.Clob myClob= null;
Connection conn = null;
// get a connection to the Oracle DBMS
// substitute the name of the machine hosting your
// Oracle server for myOracle8Server
Properties props = new Properties();
props.put("user",user);
props.put("password", password);
props.put("server",server);
try {
Driver myDriver = (Driver)
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
conn = myDriver.connect("jdbc:oracle:thin:" , props);
// set Oracle's Auto Commit feature to false.
// This is necessary when manipulating Blobs and Clobs.
conn.setAutoCommit(false);
// ============== Create Table ==================
// Create a table with a Blob and Clob column
try {
// if table does not exist, create it.
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 created.");
// ============== Initializing blob and clob values ==================
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.");
// ============== Manipulating the Blob column ======================
// get a reference to the Blob column
stmt.execute("select * from lobtest where id=44");
ResultSet rs = stmt.getResultSet();
while ( rs.next() ) {
myBlob = rs.getBlob("blobcol");
}
// Create a byte array and store some data in it
System.out.println("\nCreating the following byte array:");
int STREAM_SIZE = 10;
byte[] b = new byte[STREAM_SIZE];
for (int i=0; i < STREAM_SIZE; i++) {
b[i] = (byte)(40 + (i%20)); // range 40-60
System.out.println("byte[" + i + "] = " + b[i]);
}
// Write the byte array to a stream and store it in the Blob column
System.out.println
("\nWriting the byte array to a stream" +
" and storing it in the table as a blob...");
InputStream is = new ByteArrayInputStream(b);
OutputStream os = ((oracle.sql.BLOB) myBlob).getBinaryOutputStream();
byte[] inBytes = new byte[STREAM_SIZE];
int numBytes = is.read(inBytes);
// write the input stream to the output stream
while (numBytes > 0) {
os.write(inBytes, 0, numBytes);
numBytes = is.read(inBytes);
}
// The flush() method causes the data to be written to the table
os.flush();
//read back the blob
System.out.println("\nReading the blob back from the table and displaying:");
Statement readblob = conn.createStatement();
readblob.execute("select * from lobtest where id=44");
ResultSet rsreadblob = readblob.getResultSet();
// read the blob into a byte array and display
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 < STREAM_SIZE ; i++) {
r[i] = (byte) readis.read();
System.out.println("output [" + i + "] = " + r[i]);
}
}
// create some character data to work with
String ss = "abcdefghijklmnopqrstuvwxyz";
System.out.println("\nCreated the following string to be stored as a clob:\n" +
ss);
// ============== Manipulating the Clob column ======================
// get a reference to the clob column
stmt.execute("select * from lobtest where id=44");
ResultSet crs = stmt.getResultSet();
while ( crs.next() ) {
myClob = crs.getClob("clobcol");
java.io.OutputStream osss =
((oracle.sql.CLOB) myClob).getAsciiOutputStream();
byte[] bss = ss.getBytes("ASCII");
osss.write(bss);
osss.flush();
}
conn.commit();
// read back the 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();
// read the clob in as and ASCII stream, write to a character array, and display
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]);
}
}
// Drop the table and clean up connections
System.out.println("\nDropping table...");
Statement dropstmt = conn.createStatement();
dropstmt.execute("drop table lobtest");
System.out.println("Table dropped.");
} catch (Exception e) {
System.out.println("Exception was thrown: " + e.getMessage());
throw e;
} finally {
try {
if (conn != null)
conn.close();
} catch (SQLException sqle) {
System.out.println("SQLException was thrown: " + sqle.getMessage());
throw sqle;
}
}
}
}