关于weblogic中使用prepared statement cache后操作DDL的问题
2009-09-22 00:00:00 来源:WEB开发网This parameter is applicable only if the application gets a connection from the connection pool and then calls the getVendorConnection() method on that object. The getVendorConnection() method returns a vendor specific connection to the caller of the method which might leave the connection pool in an inconsistent state. As a result, WebLogic Server might remove it from the pool assuming it is an infected connection.
Enabling this attribute will have an impact on performance as it will essentially disable the pooling of connections. This is because connections will be removed from the pool and replaced with new connections.
因为我们这个问题必须关闭physical connection, 所以采用默认配置就可以了。你也许还会有疑问,physical connection被关闭了,如果我反复搞这么几次,connection不就被关完了?其他应用怎么办?不用担心,有connection pool呢,在getVendorConnection()被调用的时候, connection会检查Remove Infected Connections Enabled,如果为true,即这个logical connection对应的physical connection不会被重用,它会schedule一个创建physical connection的动作,以补充那个抛弃我们的phisical connection。最后关闭连接的时候,logical connection会被废弃,physical connection被关闭。
而我在测试中,尝试自己去关闭vendor connection,如下:
1 private void initializeConnection() throws SQLException
2 {
3 //this test should be run in local jvm, as oracle.jdbc.driver.T4CConnection
4 //is not a serializable object.
5 //java.io.NotSerializableException: oracle.jdbc.driver.T4CConnection
6 this.conn = this.retriver.getJBDCConnection(dsName);
7 this.wlConn = (WLConnection)this.conn;
8 this.oraConn = (OracleConnection)this.wlConn.getVendorConnection();
9 System.out.println(this.conn.toString());
10 System.out.println(this.oraConn.toString());
11 }
12
13 private void pstmtTest()
14 {
15 try
16 {
17 PreparedStatement pstmt = this.conn.prepareStatement("select * from Test");
18 System.out.println(pstmt.toString());
19 ResultSet rs = pstmt.executeQuery();
20 while(rs.next())
21 {
22 String val = rs.getString(1);
23 System.out.println(val);
24 }
25 rs.close();
26 pstmt.close();
27 this.oraConn.close();
28 this.conn.close();
29 }catch(Exception e)
30 {
31 try
32 {
33 this.oraConn.close();
34 this.conn.close();
35 }catch(Exception e1)
36 {
37 e1.printStackTrace();
38 }
39 e.printStackTrace();
40 }
41 }
测试也没什么问题,应该是oracle connection在关闭connection时先去检查connection 状态,如果已经关闭,则忽略这个动作,否则weblogic在关闭physical connection的时候应该收到SQLException。虽然这么做没什么问题,但还是建议大家按照文档上的说明,不要主动关闭phisical connection, 而让connection pool自己去管理。
总结一下:要处理这个问题,在catch到preparedStatement.execute***()抛出的 SQLException时候,将从data source中get出来的connection cast成WLConnection, 然后调用getVendorConnection()即可,不要做其他任何处理。但有一个限制,这个方法必须在server端执行, 因为Vendor Connection不是个serializable对象,不能被拿到remote JVM上去用。
时间有限,只做了Oracle的测试,没有做其他DB的测试,比如DB2, SQLServer,毕竟这个问题依赖于数据库,不保证这一做法是用于其它所有数据库。
更多精彩
赞助商链接