int oracleId = CharacterSet.ZHS16GBK_CHARSET;
oracle.sql.CharacterSet dbCharset = oracle.sql.CharacterSet.make(oracleId);
cst = (OracleCallableStatement) conn
.prepareCall("begin ?:= pkg_test.f_getList(?); end;");
//String sql = "{?=call PckgStudSltCourse.addStudPreSltCourse(?,?,?,?)}";也可以这样写
//sql="{call sp(?,?,?,?,?)}";//如果无返回值
cst.registerOutParameter(1, OracleTypes.ARRAY, "T_ARRAY");//第一个问号表示返回结果
cst.setString(2, userid);//第二个问号
cst.executeUpdate();//哪怕是个查询也用executeUpdate
oracle.sql.ARRAY simpleArray = cst.getARRAY(1);//从statement获取,而不是rs
String[] values = (String[]) simpleArray.getArray();
for (int i = 0; i < values.length; i++) {
oracle.sql.CHAR out_value = new oracle.sql.CHAR(values[i],dbCharset);
System.out.println(out_value.stringValue());
}
注意:在new oracle.sql.CHAR处,可能会报
java.lang.NoClassDefFoundError: oracle/gss/util/NLSError
at oracle.sql.CharacterSetUnknown.failCharsetUnknown(CharacterSetFactoryThin.java:178)
at oracle.sql.CharacterSetUnknown.convert(CharacterSetFactoryThin.java:145)
at oracle.sql.CHAR.(CHAR.java:147)
即missing some jar file in runtime environment
原因是weblogic没有加载web应用下的classes12.jar,而是加载了weblogic81\server\lib里的ojdbc14.jar,
而ojdbc14.jar里没有oracle.gss.util.NLSError。
修改classpath先加载classes12.jar,打印出来的是乱码,只出现乱码,这次没有出现类似这样的异常java.sql.SQLException: Non supported character set: oracle-character-set-850 。
还需要修改classpath先加载nls_charset12.jar;(必须这样,光放在web应用的lib下或光放在weblogic81\server\lib都
不行,jar包放置或加载的这三种方式是有区别的)
问题:如果使用的是ojdbc.jar,我觉得可能就不要nls_charset12.jar了,并且不需要new oracle.sql.CHAR(values[i],dbCharset)来转换
http://topic.csdn.net/t/20051110/17/4385336.html
类是通过类加载器classloader载入的。
缺省情况下web容器遵循java的标准标准类载入机制 -- 由现载入父加载器level的类。
weblogic的web容器的classloader继承自ejb容器的classloader,ejb容器的classloader又继承自 application classloader--该loader负责加载classpath下面的类,所以缺省情况下classpath下面的类会被优先载入,即使相同的类存在于web应用的lib目录。
可以通过配置文件来修改这种加载顺序,使得lib目录中的类得到优先调用,在weblogic 8.1中,方法是在weblogic.xml中加入下面的代码段:
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
weblogic 的加载顺序就是weblogic classpath优先?
一下见http://www.javaeye.com/topic/21141
ClassNotFoundException发生在装入阶段。
当应用程序试图通过类的字符串名称,使用常规的三种方法装入类,但却找不到指定名称的类定义时就抛出该异常。
NoClassDefFoundError: 当目前执行的类已经编译,但是找不到它的定义时
也就是说你如果编译了一个类B,在类A中调用,编译完成以后,你又删除掉B,运行A的时候那么就会出现这个错误
当你使用字符串去转换类,也就是尝试使用Class.forName等方法去获得一个类的时候,如果这个类不存在,就会抛出ClassNotFoundException。
而你编译的类无错,但是在运行时刻,缺乏某些必须的类时,就是抛出NoClassDefFoundError。这种情况最常见就是你在编译时,在classpath下有这个类,但是在运行时,你的classpath缺少这个类。
加载时从外存储器找不到需要的class就出现ClassNotFoundException
连接时从内存找不到需要的class就出现NoClassDefFoundError
问题:加载和连接的区别
创建测试用表
CREATETABLE T_TEST(
I_ID NVARCHAR(20),
I_NAME NVARCHAR(20)
)
一:无返回值的存储过程
1、建立存储过程
CREATE OR REPLACE PROCEDURE TESTA(PARA1 IN VARCHAR2,PARA2 IN VARCHAR2) AS
BEGIN
INSERT INTO T_TEST (I_ID,I_NAME) VALUES (PARA1, PARA2);
END TESTA;
2、相应的JAVA程序
import java.sql.*;
import java.io.OutputStream;
import java.io.Writer;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import oracle.jdbc.driver.*;
public class TestProcedureOne {
public TestProcedureOne() {
}
public static void main(String[] args ){
String driver = "oracle.jdbc.driver.OracleDriver";
String strUrl = "jdbc:oracle:thin:@192.168.10.216:1521:ctbu";
Statement stmt = null;
ResultSet rs = null;
Connection conn = null;
CallableStatement cstmt = null;
try {
Class.forName(driver);
conn = DriverManager.getConnection(strUrl, "dbname", "password");
CallableStatement proc = null;
proc = conn.prepareCall("{ call dbname.TESTA(?,?) }");
proc.setString(1, "100");
proc.setString(2, "TestOne");
proc.execute();
}
catch (SQLException ex2) {
ex2.printStackTrace();
}
catch (Exception ex2) {
ex2.printStackTrace();
}
finally{
try {
if(rs != null){
rs.close();
if(stmt!=null){
stmt.close();
}
if(conn!=null){
conn.close();
}
}
}
catch (SQLException ex1) {
}
}
}
}
二:有返回值的存储过程(非列表)
1、存储过程为
CREATE OR REPLACE PROCEDURE TESTB(PARA1 IN VARCHAR2,PARA2 OUT VARCHAR2) AS
BEGIN
SELECT INTO PARA2 FROM TESTTB WHERE I_ID= PARA1;
END TESTB;
2、JAVA代码
public class TestProcedureTWO {
public TestProcedureTWO() {
}
public static void main(String[] args ){
String driver = "oracle.jdbc.driver.OracleDriver";
String strUrl = "jdbc:oracle:thin:@192.168.10.216:1521:ctbu";
Statement stmt = null;
ResultSet rs = null;
Connection conn = null;
try {
Class.forName(driver);
conn = DriverManager.getConnection(strUrl, "dbname", "password");
CallableStatement proc = null;
proc = conn.prepareCall("{ call HYQ.TESTB(?,?) }");
proc.setString(1, "100");
proc.registerOutParameter(2, Types.VARCHAR);
proc.execute();
String testPrint = proc.getString(2);
System.out.println("=testPrint=is="+testPrint);
}
catch (SQLException ex2) {
ex2.printStackTrace();
}
catch (Exception ex2) {
ex2.printStackTrace();
}
finally{
try {
if(rs != null){
rs.close();
if(stmt!=null){
stmt.close();
}
if(conn!=null){
conn.close();
}
}
}
catch (SQLException ex1) {
}
}
}
}
}
注意,这里的proc.getString(2)中的数值2并非任意的,而是和存储过程中的out列对应的,如果out是在第一个位置,那就是 proc.getString(1),如果是第三个位置,就是proc.getString(3),当然也可以同时有多个返回值,那就是再多加几个out 参数了。
三:返回列表
由于oracle存储过程没有返回值,它的所有返回值都是通过out参数来替代的,列表同样也不例外,但由于是集合,所以不能用一般的参数,必须要用pagkage了.所以要分两部分。
1、在SQL*PLUS中建一个程序包
CREATE OR REPLACE PACKAGE TESTPACKAGE AS
TYPE Test_CURSOR IS REF CURSOR;
procedure TESTC(cur_ref out Test_CURSOR);
end TESTPACKAGE;
建立存储过程,存储过程为:
create or replace package body TESTPACKAGE as
procedure TESTC(cur_ref out Test_CURSOR) is
begin
OPEN cur_ref FOR SELECT * FROM T_TEST;
end TESTC;
END TESTPACKAGE;
可以看到,它是把游标(可以理解为一个指针),作为一个out 参数来返回值的。
JAVA程序如下:
import java.sql.*;
import java.io.OutputStream;
import java.io.Writer;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import oracle.jdbc.driver.*;
public class TestProcedureOne {
public TestProcedureOne() {
}
public static void main(String[] args ){
String driver = "oracle.jdbc.driver.OracleDriver";
String strUrl = "jdbc:oracle:thin:@192.168.10.216:1521:ctbu";
Statement stmt = null;
ResultSet rs = null;
Connection conn = null;
CallableStatement cstmt = null;
try {
Class.forName(driver);
conn = DriverManager.getConnection(strUrl,"databasename" "password");
CallableStatement proc = null;
proc = conn.prepareCall("{ call cqsb.TESTA(?,?) }");
proc.setString(1, "100");
proc.setString(2, "TestOne");
proc.execute();
}
catch (SQLException ex2) {
ex2.printStackTrace();
}
catch (Exception ex2) {
ex2.printStackTrace();
}
finally{
try {
if(rs != null){
rs.close();
if(stmt!=null){
stmt.close();
}
if(conn!=null){
conn.close();
}
}
}
catch (SQLException ex1) {
}
}
}
}
特别注意:
1、在执行前一定要先把oracle的驱动包放到class路径里。
2、Toad在我建立存储过程中搞了很多莫名的错误,多数是没有创建成功而不报错,
或者是创建有误而不提示,应当引起重视。所以最好还是在SQL*PLUS玩这些。
3、在SQL*PLUS中的换行是无效的,要换行的时候一定要空格结尾,特别是你直接复制代码的时候!