分享
 
 
 

痛苦的windows20003+oracle10g+tomcat连接池迁移之旅

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

我的痛苦的windows20003+oracle10g+tomcat连接池迁移之旅

项目开发中完成,在开发环境中是在windowsxp和用自己的连接池开发的,oracle数据库的版本是8。17。

重大问题1:windows2003的问题,微软的正版软件我看也不见的好到那里去。那个windows20003server版本比盗版的还低,装上后还需要激活,激活的工序可是麻烦的要了命。他好像使用了限制一台计算机使用,如果你再这个计算机上安装了这套软件,并且通过电话激活或internet激活方式激活了该操作系统,那么这套操作系统只能再这个计算机上使用了,其他的计算机上不能安装了,安装完了,无法激活!

后来他们销售的通过和微软的多次打电话才解决了这个问题。保证了在那台服务器上能激活。

重大问题2:网上下载的oracle10g无法安装。安装中间报错误:unable to create item in start menu and desktop........,多么郁闷的问题。多次网上查询都没有着相关的问题。找遍了google也没有找到。难道就没有人遇到过。让他们集成的人多次重新安装系统还是不行。到底是那里的问题呢?后来想到了需要用别的软件试验一下,于是拷了一个金山词霸进行安装,奇怪的是他显示的界面都是乱码,最后也报告无法在开始菜单和桌面上创建快捷方式。到底是那里的问题了,开始以为是权限的问题,修改administrator的权限多次,都没解决,最后才知道了是windows本地语言设置的问题。原来是他没有设置好本地的语言。中文的版本,本地语言设置为英文就出现了这么多无法解释的错误。真是要了人的命。不过现在想想,也是,他按照英文找中文的开始菜单,当然找不到了。

重大问题3:

开始搬迁程序了。导入了oracle数据库,从oracle8上备份到oracle10g上到没有什么问题。主要是我们的dba比较厉害。然后开始配置打包程序war文件。放到tomcat上,在tomcat上配置了连接池。修改了程序中获得连接的地方。放上去,发现不行。报错:network adapter........好像是网络没有找到。哦,发现是网线掉了。后来报错,驱动不对,到oracle安装的计算机上找到了他下面的lib\jdbc\的驱动替换掉以前的oracle8的程序。重新部署,报告说找不到驱动。对了把驱动程序到拷贝到了tomcat\common\lib\,然后启动,连接池成功配置。成功登陆了系统。ok?no.最后一个可怕的问题出现了。再读取oracle10g中clob字段的时候报错误。ClassCastException,查看包错误的程序就在:oracle.sql.CLOB clog=(Oracle.sql.CLOB)rs.getClob("clob_text");开始我们认为这是一个多么难解决的问题。我估计可能是那里的转换类型错误了。没想到这个问题害的我整整折腾了2天。

棘手的痛苦的问题4

这个问题确实不那么简单。我开始怀疑是oracle10g驱动的问题。我加载了全部的oracle10g的驱动,尽管网上说如果是在jdk1。4以上的版本,只需要加载其中的一个ojdbc14。jar包。但是事情害是不行。错误仍然,我开始在google上找这个问题。在sun的开坛上的这个帖子给了我很大的帮助:oracle.sql.CLOB+ClassCastException 这个问题网上很多。

http://forum.java.sun.com/thread.jspa?threadID=349880&start=15

这个帖子有各种各样的解决方法。我挨个试验了。

看到了他们使用oracle提供的创建临时clob的方法。

oracle.sql.CLOB newClob = oracle.sql.CLOB.createTemporary(conn, false, oracle.sql.CLOB.DURATION_CALL);

依然不行,还是同样的错误发生,我急了,让他打印看看取道的到底是什么对象,缺是java.sql.Clob这个我早知道,打印了了白打,我想把他转换到oracle的clob就是不行。使用创建临时的clob是他的那个连接不能使用。该死的,这个从tomcat5。0中获得的连接池怎么不行呢。后来看到帖子上有人用con的类型转换,转换成oraclejdbcconnnection。于是我也试验了。还不行。后来在其他西班牙的网站上看到了他使用了一个jboss下的包转换wapper,转换成jboss的连接,说是成功了。我开始试验,代码拷贝过来,发现没有jboss的那个common包,于是网上down下来。加载进去,编译通过。放到服务器上。这次不包错误了,但是执行到那里,你等半个小时都过去去。一个字,烂。

马上抛开了这个方法。jboss的东西抛弃掉了。后来在oracle的官方网站上看到熬了oracle公司提供的oracle10g中如何使用jdbc的例子。试验了。还是不行,真不知道他们这些东西是怎么提供处来的。不过在这理看到一个oracle驱动加载的新的方法

import java.sql.Connection;

import java.sql.DriverManager;

import oracle.jdbc.OracleDriver;

import java.util.Properties;

..........

// Load the database details into the variables.

String url = "jdbc:oracle:thin:@localhost:1521:orcl";

String user = "scott";

String password = "tiger";

// Create the properties object that holds all database details

Properties props = new Properties();

props.put("user", user );

props.put("password", password);

props.put("SetBigStringTryClob", "true");

// Load the Oracle JDBC driver class.

DriverManager.registerDriver(new OracleDriver());

// Get the database connection

Connection conn = DriverManager.getConnection( this.url, this.props );

我怀疑props.put("SetBigStringTryClob", "true");东西很有用,于是在tomcat的连接池配置的server.xml中也添加了这个属性参数。配置后,在读取clob的时候,我按照oracle网站提供的直接使用了getString这个方法,庆幸的是ok了,可以读取出来了。

但是更新方法不行,按照他们给提供的。

这是他们给提供的方法:

ClobManipulationIn10g

/* * @author Savitha * @version 1.0 * * Development Environment : Oracle JDeveloper 10g * Name of the Application : ClobManipulationIn10g.java * Creation/Modification History : * * Savitha 17-Mar-2004 Created. */package oracle.otnsamples.jdbc;// Java SQL classesimport java.sql.Connection;import java.sql.DriverManager;import java.sql.Statement;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;// Oracle JDBC driver classimport oracle.jdbc.OracleDriver;// Java IO classesimport java.io.IOException;import java.io.BufferedReader;import java.io.FileNotFoundException;import java.io.FileReader;//Java Util classesimport java.util.Properties; /** * This class demonstrates the Oracle JDBC 10g enhanced features for inserting * and retrieving CLOB data from the database. Using the new features, large * data of more than 32765 bytes can be inserted into the database using the * existing PreparedStatement.setString() and PreparedStatement.getString() * methods. */public class ClobManipulationIn10g { /* Database Connection object */ private Connection conn = null; /* Variables to hold database details */ private String url = null; private String user = null; private String password = null; // Create a property object to hold the username, password and // the new property SetBigStringTryClob. private Properties props = new Properties(); /* String to hold file name */ private String fileName = null; /** * Default Constructor to instantiate and get a handle to class methods * and variables. */ public ClobManipulationIn10g(String fileName) { this.fileName = fileName; } /** * Main runnable class. */ public static void main(String[] args) throws SQLException { // Instantiate the main class. ClobManipulationIn10g clobManipulationIn10g = new ClobManipulationIn10g(args[0]); // Load the Oracle JDBC driver class. DriverManager.registerDriver(new OracleDriver()); // Load the database details into the variables. String dbUrl = "jdbc:oracle:thin:@::"; clobManipulationIn10g.url = dbUrl; // Replace the username where the table 'clob_tab' was created. clobManipulationIn10g.user = "scott"; // Replace the password of the username. clobManipulationIn10g.password = "tiger"; // Populate the property object to hold the username, password and // the new property 'SetBigStringTryClob' which is set to true. Setting // this property allows inserting of large data using the existing // setString() method, to a CLOB column in the database. clobManipulationIn10g.props.put("user", clobManipulationIn10g.user ); clobManipulationIn10g.props.put("password", clobManipulationIn10g.password); clobManipulationIn10g.props.put("SetBigStringTryClob", "true"); // Check if the table 'CLOB_TAB' is present in the database. clobManipulationIn10g.checkTables(); // Call the methods to insert and select CLOB from the database. clobManipulationIn10g.insertClob(); clobManipulationIn10g.selectClob(); } /* * This method will insert the data into a CLOB column in the database. * Oracle JDBC 10g has enhanced the existing PreparedStatement.setString() * method for setting the data more than 32765 bytes. So, using setString(), * it is now easy to insert CLOB data into the database directly. */ private void insertClob() throws SQLException { // Create a PreparedStatement object. PreparedStatement pstmt = null; try { // Create the database connection, if it is closed. if ((conn==null)||conn.isClosed()){ // Connect to the database. conn = DriverManager.getConnection( this.url, this.props ); } // Create SQL query to insert data into the CLOB column in the database. String sql = "INSERT INTO clob_tab VALUES(?)"; // Read a big file(larger than 32765 bytes) String str = this.readFile(); // Create the OraclePreparedStatement object pstmt = conn.prepareStatement(sql); // Use the same setString() method which is enhanced to insert // the CLOB data. The string data is automatically transformed into a // clob and inserted into the database column. Make sure that the // Connection property - 'SetBigStringTryClob' is set to true for // the insert to happen. pstmt.setString(1,str); // Execute the PreparedStatement pstmt.executeUpdate(); } catch (SQLException sqlex) { // Catch Exceptions and display messages accordingly. System.out.println("SQLException while connecting and inserting into " + "the database table: " + sqlex.toString()); } catch (Exception ex) { System.out.println("Exception while connecting and inserting into the" + " database table: " + ex.toString()); } finally { // Close the Statement and the connection objects. if (pstmt!=null) pstmt.close(); if (conn!=null) conn.close(); } } /* * This method reads the CLOB data from the database by using getString() * method. */ private void selectClob() throws SQLException { // Create a PreparedStatement object PreparedStatement pstmt = null; // Create a ResultSet to hold the records retrieved. ResultSet rset = null; try { // Create the database connection, if it is closed. if ((conn==null)||conn.isClosed()){ // Connect to the database. conn = DriverManager.getConnection( this.url, this.props ); } // Create SQL query statement to retrieve records having CLOB data from // the database. String sqlCall = "SELECT clob_col FROM clob_tab"; pstmt= conn.prepareStatement(sqlCall); // Execute the PrepareStatement rset = pstmt.executeQuery(); String clobVal = null; // Get the CLOB value from the resultset while (rset.next()) { clobVal = rset.getString(1); System.out.println("CLOB length: "+clobVal.length()); } } catch (SQLException sqlex) { // Catch Exceptions and display messages accordingly. System.out.println("SQLException while connecting and querying the " + "database table: " + sqlex.toString()); } catch (Exception ex) { System.out.println("Exception while connecting and querying the " + "database table: " + ex.toString()); } finally { // Close the resultset, statement and the connection objects. if (rset !=null) rset.close(); if (pstmt!=null) pstmt.close(); if (conn!=null) conn.close(); } } /** * Method to check if the table ('CLOB_TAB') exists in the database; if not * then it is created. * * Table Name: CLOB_TAB * Column Name Type * ----------------------------------- * col_col CLOB */ private void checkTables() { Statement stmt = null; ResultSet rset = null; try { // Create the database connection, if it is closed. if ((conn==null)||conn.isClosed()){ // Connect to the database. conn = DriverManager.getConnection( this.url, this.props ); } // Create Statement object stmt = conn.createStatement(); // Check if the table is present rset = stmt.executeQuery(" SELECT table_name FROM user_tables "+ " WHERE table_name = 'CLOB_TAB' "); // If the table is not present, then create the table. if (!rset.next()) { // Table does not exist, create it stmt.executeUpdate(" CREATE TABLE clob_tab(clob_col CLOB)"); } } catch (SQLException sqlEx) { System.out.println("Could not create table clob_tab : " +sqlEx.toString()); } finally { try { if( rset != null ) rset.close(); if( stmt != null ) stmt.close(); if (conn!=null) conn.close(); } catch(SQLException ex) { System.out.println("Could not close objects in checkTables method : " +ex.toString()); } } } /* * This method reads the specified text file and, returns the content * as a string. */ private String readFile() throws FileNotFoundException, IOException{ // Read the file whose content has to be passed as String BufferedReader br = new BufferedReader(new FileReader(fileName)); String nextLine = ""; StringBuffer sb = new StringBuffer(); while ((nextLine = br.readLine()) != null) { sb.append(nextLine); } // Convert the content into to a string String clobData = sb.toString(); // Return the data. return clobData; }}

最后只好再想其他的方法。发现有人研究tomcat的连接池,他自己写了tomcat的连接的转换类,来获得他的实际的连接实现类:

tempclob= CLOB.createTemporary(DbcpNativeJdbcExtractor.getNativeConnection(conn), true, CLOB.DURATION_SESSION);

public class DbcpNativeJdbcExtractor{

public static Connection getNativeConnection(Connection con) throws SQLException {

if (con instanceof DelegatingConnection) {

Connection nativeCon = ((DelegatingConnection) con).getInnermostDelegate();

// For some reason, the innermost delegate can be null: not for a

// Statement's Connection but for the Connection handle returned by the pool.

// We'll fall back to the MetaData's Connection in this case, which is

// a native unwrapped Connection with Commons DBCP 1.1.

return (nativeCon != null ? nativeCon : con.getMetaData().getConnection());

}

return con;

}

}

我也试验了,编译每问题。运行到数据库执行更新clob类型的时候,就没反映了,死掉了。该死的,

这种获得tomcat实际连接的转行都不行。我服了。。。。。。。。

继续想办法。发现在开始的那个帖子上。

http://forum.java.sun.com/thread.jspa?threadID=349880&start=15&tstart=0

上给提供了一种可以用流来处理clob的类型。但我开始试验没有通过,现在又开始重新研究,

别人都说行。我这里怎么就不行呢。哦。我突然发现程序中又一个变量的bug。

tmd,可能是他的原因。我修改了程序。重新运行。ok。终于搞定了。我的代码也乱成一团了。

但最后实现clob的操作的方法总结了2条:

1。如果读取clob类型的字段,你设置上"SetBigStringTryClob", "true"这个环境变量,应该没有问题的。

2、如果你要更新clob。如果是低于oracle10g的版本。用一般的方法都可以。但是10g中就用流来处理吧。

其他的转换成oracle.sql.CLOB的方法我是每找到,主要是老报错误。这和使用tomcat5的连接池有关系。

如果使用自己的连接池,问题应该不大。

参考代码:1。可以直接使用getString方法来获得clob的数据

/**

*从ResultSet种来获得某列的CLOB的String值

* @param colName

* @return

*/

public String getClobStr(ResultSet rs, String columnName) throws SQLException {

//

// StringBuffer sb = new StringBuffer();

// Writer clobWriter = ( (oracle.sql.CLOB) rs.getClob(columnName)).

// getCharacterOutputStream();

//

// try {

// clobWriter.write(sb.toString());

// clobWriter.close();

// }

// catch (IOException ex1) {

// ex1.printStackTrace();

// }

//

// return sb.toString();

// Object value =((OracleResultSet) rs).getCLOB(columnName);

return rs.getString(columnName);

// Object value =rs.getClob(columnName);

// System.out.println("getObject(columnName).getClass()======="+value.getClass());

// CLOB clob = (CLOB) value;

// java.io.Reader instream = clob.getCharacterStream();

// // create temporary buffer for read

// char[] buffer = new char[10000];

//

// String l = "";

// try {

// long length = instream.read(buffer);

//

// // length of characters read

//

// l = null;

// l = String.copyValueOf(buffer);

// instream.close();

// }

// catch (IOException ex) {

// ex.printStackTrace();

// }

//

// return l.trim();

}

/**

* 要更新clob类型的数据

* @param idName 你的表的主键的名称

* @param id 你的主键的值如:100000

* @param tableName 你要操作的表名

* @param column 你的要更新的字符串的列名的集合

* @param value 你要更新的CLOB的值字符串集合

*/

public void updateClob(String idName, long id, String tableName,

String[] column, String[] value) {

//

String cloStr = "";

if (column != null)

for (int i = 0; i < column.length; i++) {

cloStr += column[i] + "=?,";

}

cloStr = cloStr.substring(0, cloStr.length() - 1);

String parStr = getParaStr(value.length);

String sql = "";

sql = "update " + tableName + " set " + cloStr + " where " + idName + "=" +

id;

System.out.println("sql = " + sql);

List list = new ArrayList();

PreparedStatement opstmt = null;

try {

opstmt = con.prepareStatement(sql);

for (int i = 0; i < column.length; i++) {

StringReader fis = new java.io.StringReader(value[i]);

opstmt.setCharacterStream( (i + 1), fis, (int) value[i].length());

System.out.println("ps.setAsciiStream((i+1)==" + (i + 1));

list.add(fis);

}

opstmt.executeUpdate();

con.commit();

for (int i = 0; i < list.size(); i++) {

try {

( (StringReader) list.get(i)).close();

}

catch (Exception ex) {

ex.printStackTrace();

}

}

}

catch (SQLException sqlex) {

sqlex.printStackTrace();

}

finally {

try {

con.setAutoCommit(true);

if (opstmt != null) {

opstmt.close();

}

}

catch (SQLException sqlex) {

sqlex.printStackTrace();

}

}

}

//多次修改,多次的修改记录的代码片断。没有成功的。留个纪念:

=============垃圾代码===================

oracle.sql.CLOB tempclob = oracle.sql.CLOB.createTemporary(((WrappedConnection) con).getUnderlyingConnection() , false, oracle.sql.CLOB.DURATION_CALL);

// oracle.sql.CLOB tempclob = CLOB.createTemporary(con, true, CLOB.DURATION_SESSION);

// tempclob.open(CLOB.MODE_READWRITE); //mode d'ouverture

// oracle.sql.CLOB tempclob= CLOB.createTemporary(DbcpNativeJdbcExtractor.getNativeConnection(con), true, CLOB.DURATION_SESSION);

/* oracle.sql.CLOB tempclob = oracle.sql.CLOB.createTemporary(con, false, oracle.sql.CLOB.DURATION_CALL);

Writer tempClobWriter = tempclob.getCharacterOutputStream();

try {

tempClobWriter.write(value[i].toCharArray());

tempClobWriter.flush();

tempClobWriter.close();

tempclob.close();

}

catch (SQLException ex) {

ex.printStackTrace();

}

catch (IOException ex) {

ex.printStackTrace();

}

ps.setClob((i+1),tempclob);

*/

ps.setString((i=1),value[i]);

// oracle.sql.CLOB newClob = oracle.sql.CLOB.createTemporary(con, false, oracle.sql.CLOB.DURATION_CALL);

// newClob.putString(1,value[i]);

// opstmt.setClob( (i + 1), newClob);

StringReader fis =new java.io.StringReader (value[i]);

ps.setCharacterStream((i+1), fis, (int) value[i].length());

System.out.println("ps.setAsciiStream((i+1)=="+(i+1));

=============垃圾代码===================

这次经历。我让我长了不少知识,认识到许多版本之间的区别。也感觉到了windows2003的糟粕,oracle10g驱动的烂。tomcat连接池的局限性等等。

希望能给别人带来点小小的帮助。让我们引以为戒,深入研究。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有