BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
WebLogic JDBC & Transaction 版精华帖整理
崔飞飞 (DEV2DEV ID:CONVERSE)
除了论坛内的精华内容,增加了一些WEBLOGIC JDBC 的基础配置知识。论坛内有许多
问题是没有回答和解决的,对于这部分内容如果有相类似的就进行归类,其他的就通过查找
相关的资料进行回答,实在解决不了的,整理的时候都做了记录。
整理的过程中对很多原先不清晰的概念,有了更清晰深刻的理解,希望整理后的内容也
能对大家起到这样的作用,限于本人的水平,如有不正确或遗漏之处请大家补充完善。
WebLogic JDBC & Transaction 版精华总结 第 2 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
目 录
WebLogic JDBC & Transaction 版精华帖整理............................................................................1
目 录.............................................................................................................................................2
1 JDBC 连接池配置.........................................................................................................................4
1.1 配置连接池 FOR WEBLOGIC 8.1 ..................................................................................4
1.1.1 通过程序配置连接池.............................................................................................7
1.1.2 通过程序查看连接池运行状态信息.....................................................................7
1.2 配置连接池常见问题........................................................................................................8
1.2.1 连接有效性测试选项.............................................................................................8
1.2.2 不同类型驱动的区别与选择..................................................................................8
1.2.3 JDBC 连SQL SERVER 数据库的常见问题........................................................10
1.2.4 XA-DRIVER 与普通DRVIER 的区别................................................................11
2 JDBC 连接池使用.......................................................................................................................12
2.1 数据库连接方法总结......................................................................................................12
2.2 数据库连接池使用常见问题..........................................................................................13
2.2.1 连接泄漏(pool connection leak).......................................................................13
2.2.2 处理ORACLE 的BLOB 字段.............................................................................15
2.2.3 配置连接池成功程序使用出问题........................................................................16
3 事务处理.....................................................................................................................................17
3.1 事务的属性和基本概念..................................................................................................17
3.1.1 Local transaction 和Distributed transaction 有什么区别? ...................................17
3.1.2 跨资源的Transaction 如何控制? .......................................................................18
3.1.3 XA 的driver,是否也是一种distribued transaction? .......................................18
3.1.4 JTA 和JTS 到底有什么区别? .............................................................................19
3.1.5 分布式事务提交或回滚后恩能够否关闭连接? ...............................................19
4 论坛常见问题..............................................................................................................................20
4.1 有谁说说DriverManger 的性能和DataSource 的区别? ..........................................20
4.2 PreparedStatement 和Statement 的区别在什么地方? ..........................................20
4.3 解释一下 connection pool 中的 physical connection 和 logic connection 的
区别........................................................................................................................................20
4.4 连接池中连接使用出错: connection reset by peer, 原因? ............................21
4.5 数据库链接资源该怎么优化?........................................................................................21
4.6 如果页面没有执行到关闭连接的地方,页面被关闭,如何去释放这个建立的连接?
WebLogic JDBC & Transaction 版精华总结 第 3 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
...............................................................................................................................................21
5 附录...........................................................................................................................................23
5.1 代码1---连接池设置代码.............................................................................................23
5.2 代码2---连接池监控代码.............................................................................................24
WebLogic JDBC & Transaction 版精华总结 第 4 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
1 JDBC 连接池配置
1.1 配置连接池 FOR WEBLOGIC 8.1
论坛内经常有人询问如何配置连接池的问题,这里把配置的详细过程都再重复一遍,并
包含论坛内对配置连接池出现的问题回答进行整理。
STEP 1: 数据库类型和驱动类型的选择,对于各种TYPE 的驱动附录内容会做介绍。
STEP 2:连接池连接属性配置,连接URL,用户名/密码,数据库服务名。
WebLogic JDBC & Transaction 版精华总结 第 5 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
STEP 3:测试连接池配置是否正确。
STEP 4:测试成功后进行部署。
STEP 5:部署成功,选择该连接进行连接池的参数配置。
WebLogic JDBC & Transaction 版精华总结 第 6 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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: 如果选择了这个选项,服务器就会在把连接返回给连接池
之前对其进行测试。
WebLogic JDBC & Transaction 版精华总结 第 7 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
• 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(连接池监控)
WebLogic JDBC & Transaction 版精华总结 第 8 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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 驱动的类型与选择,在配置连接池的时候进行选择。
WebLogic JDBC & Transaction 版精华总结 第 9 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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 模式。这种模式的产品比较适用于企业内部互联网,如若支持国际互联网,
还需添加对安全、穿过防火墙访问等的支持。
WebLogic JDBC & Transaction 版精华总结 第 10 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
【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 里保留的关键字。
WebLogic JDBC & Transaction 版精华总结 第 11 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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.htmlWebLogic JDBC & Transaction 版精华总结 第 12 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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";
WebLogic JDBC & Transaction 版精华总结 第 13 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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.htmlhttp://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.jspWebLogic JDBC & Transaction 版精华总结 第 14 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
在WLS 7.0 中已经可以通过GC 收leaked connection 了, 不过
JDBCConnectionPoolRuntimeMBean 的getLeakedConnectionCount 好像没跟上.
WebLogic JDBC & Transaction 版精华总结 第 15 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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 网站的例子代码)
WebLogic JDBC & Transaction 版精华总结 第 16 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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();
WebLogic JDBC & Transaction 版精华总结 第 17 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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 的区别。 注意上
面的概念就应该知道了。
WebLogic JDBC & Transaction 版精华总结 第 18 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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 的,所以来说跨库就属于分布式事务了。
WebLogic JDBC & Transaction 版精华总结 第 19 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
3.1.4 JTA 和JTS 到底有什么区别?
JTA 是进行事务调用的API, JTS 则是事务的具体实现,实现事务管理,资源管理,以
及底层事务通讯管理。
3.1.5 分布式事务提交或回滚后能够否关闭连接?
在事务完成后可以关闭连接。
关于事务更多的内容请参看
http://e-docs.bea.com/wls/docs60/faq/transactions.htmlWebLogic JDBC & Transaction 版精华总结 第 20 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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,
WebLogic JDBC & Transaction 版精华总结 第 21 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
至于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 有什么区别啊?
WebLogic JDBC & Transaction 版精华总结 第 22 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
在单SERVER 的配置中使用multipool,主要用途有两个1>高可靠性;2>负载均衡。可
根据实际需求选择其一。Multipool 的高可靠性只用于数据库停止的一种情况,当数据库挂
起或数据库连接用光时都不起作用。
4.8 weblogic 里数据源和连接池的关系是什么?
连接池可以看作是存储一群连接对象的容器,而数据源是得到一个连接的统一接口.
4.9 配置连接池连接Oarcle RAC 集群
BEA 官方资料:
http://e-docs.bea.com/wls/docs81/jdbc/oracle_rac.htmlWebLogic JDBC & Transaction 版精华总结 第 23 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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 失败", "
WebLogic JDBC & Transaction 版精华总结 第 24 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
错误", 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() {
}
//获取当前的活动连接
WebLogic JDBC & Transaction 版精华总结 第 25 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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);
}
WebLogic JDBC & Transaction 版精华总结 第 26 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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>
WebLogic JDBC & Transaction 版精华总结 第 27 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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")) {
WebLogic JDBC & Transaction 版精华总结 第 28 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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);
WebLogic JDBC & Transaction 版精华总结 第 29 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
// ============== 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
WebLogic JDBC & Transaction 版精华总结 第 30 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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() ) {
WebLogic JDBC & Transaction 版精华总结 第 31 页总 31 页
BEA dev2dev 中国网站
http://dev2dev.bea.com.cn 版权所有
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;
}
}
}
}
发表于 @
2008年06月03日 10:30:00 | | 编辑|
举报| 收藏