使用OCCI交互CLOB
来源:互联网 发布:spss数据分析简单案例 编辑:程序博客网 时间:2024/05/17 23:06
前言
这篇文章是《Weblogic与Tuxedo互连指南》的延续,Tuxedo是交易中间件,我手上的项目是用来接受请求后再转发到另一个Tuxedo中的环境模式。中心转发时需要记录日志以及一些业务逻辑处理,需要与数据库交互,中心是用c++写的,使用的occi与Oracle连接。数据传递使用XML。那么现在问题来了,当客户端传递大xml到中心时,Tuxedo服务进程就died。我是Java程序员,在这之前对c++只有HelloWorld的接触,指针也只是听说过。各种调试后找到了服务died的原因,原因在于与数据库交互时,数据量大的原因,导致服务挂起,数据库过程定义入参是clob,但在c++里面set的string,好吧,以上全是环境铺垫,下面进入正题,occi与oracle的clob传入及传出。
步骤
1、定义Oracle过程,传入和传出都使用CLOB
2、编写C++代码调用Oracle过程,实现CLOB传入及传出实现Oracle部分
1、建表create table TESTCLOB( CID NUMBER(38), DETAIL CLOB, WRITEDATE DATE);2、建过程
CREATE OR REPLACE PACKAGE Pkg_test IS PROCEDURE p_test_clob(prm_input IN CLOB, --传入 prm_output OUT CLOB, --传出 prm_lengthb OUT INTEGER); --传出长度END Pkg_test;CREATE OR REPLACE PACKAGE BODY Pkg_test ISPROCEDURE p_test_clob(prm_input IN CLOB, -- 传入 prm_output OUT CLOB, -- 传出 prm_lengthb OUT INTEGER)-- 传出长度AS clob_buffer CLOB; --缓冲区 input CLOB; --input分段 n_out VARCHAR2(100); n_length INTEGER; input_length INTEGER; --input长度 base_length INTEGER; --基本分段的长度 index_length INTEGER;BEGIN prm_lengthb := 0; --初始化传出长度为0 base_length := 16383; --每段长度16383 index_length := 16383; --第一段长度16383 /* 写入处理 */ --1、清空clob字段 update testclob set detail = empty_clob() where cid = '1'; --2、将clob写给缓冲区 select detail into clob_buffer from testclob where cid = '1'; --3、截取input,一次写入过大会报错,故截取多次写入 input_length := DBMS_LOB.getlength(prm_input); input := dbms_lob.substr(prm_input,base_length,1); --4、写入第一段 DBMS_LOB.OPEN(clob_buffer, DBMS_LOB.LOB_READWRITE); DBMS_LOB.WRITE(clob_buffer, DBMS_LOB.getlength(input), 1, input); --5、如果input超过第一段长度就分段截取写入,每次16383 while input_length > index_length loop input := dbms_lob.substr(prm_input,base_length,index_length); index_length := index_length + base_length; DBMS_LOB.WRITEAPPEND(clob_buffer,DBMS_LOB.getlength(input), input); end loop; --6、写入表字段 update testclob set detail = clob_buffer where cid = '1'; --7、关闭缓存区 DBMS_LOB.CLOSE(clob_buffer); /* 传出处理 */ --1、创建临时空间 dbms_lob.createtemporary(prm_output, true); --2、往prm_output写入‘Hi,你好’,200次 n_out := 'Hi,你好!'; --3、关键点,获取字节长度,C++中使用 n_length := lengthb(n_out); for i in 1..200 loop dbms_lob.writeappend(prm_output, length(n_out), n_out); --4、累加写入长度 prm_lengthb := prm_lengthb + n_length; end loop; END p_test_clob;END Pkg_test;
实现C++部分
#include "stdafx.h"#include <iostream>#include <occi.h>using namespace std;using namespace oracle::occi;#pragma comment (lib, "C:\\oracle\\product\\10.2.0\\db_1\\OCI\\lib\\MSVC\\oraocci10.lib")int main(){ Environment *env=Environment::createEnvironment(Environment::DEFAULT); string name = "test"; string pass = "test"; string srvName = "192.168.43.1:1521/orcl"; string lstr_input = "HelloWorld"; Statement *stmt; try{ //1、连接数据库 Connection *conn = env->createConnection(name, pass,srvName); cout<<"conn success"<<endl; //2、执行一个oracle方法,创建clob的临时空间,与oracle过程里面的用法一致 stmt = conn->createStatement("begin dbms_lob.createtemporary(:p1,FALSE);end;"); stmt->registerOutParam(1,OCCICLOB); stmt->executeUpdate(); //3、取出上一步的对象 Clob clob_input = stmt->getClob(1); //4、写入字符传到clob clob_input.write((unsigned int)lstr_input.size(), (unsigned char*)lstr_input.c_str(),(unsigned int)lstr_input.size()); conn->terminateStatement (stmt); //5、调用业务过程 stmt = conn->createStatement("BEGIN Pkg_test.p_test_clob(:v1,:v2,:v3); END;"); stmt->setClob(1,clob_input); //传入包含字符串的clob stmt->registerOutParam(2,OCCICLOB); stmt->registerOutParam(3,OCCIINT); stmt->executeUpdate (); //6、取出clob Clob clob_ouput = stmt->getClob(2); //返回的字符数 unsigned int cloblen = clob_ouput.length(); //7、分配空间用于存储返回的clob中的字符 // 空间大小为过程返回的第3个参数,即过程中累加的字节数 char *chr_out = (char *) malloc(stmt->getInt(3)); //8、设置字符类型,避免中文乱码 clob_ouput.setCharSetForm(OCCI_SQLCS_IMPLICIT); //9、读取clob中的数据到内存空间 clob_ouput.open(OCCI_LOB_READONLY); clob_ouput.read(cloblen*2, (unsigned char*)chr_out, cloblen*2, 1); clob_ouput.close(); //10、重要的一步,调试了几天才明白,char的结尾加'\0' // 关键是结尾的位置不是cloblen的字符长度,而是过程返回的字节长度 // Java中没有这些问题,纠结了好长时间。没有'\0'结尾时读取的值最后 // 有乱码,若给的下标位置没正确,则读取的字符被截断 chr_out[stmt->getInt(3)]='\0'; string str_ouput = chr_out; cout<<str_ouput.c_str()<<endl; int j; cin>>j; conn->terminateStatement (stmt); env->terminateConnection(conn); } catch(SQLException e) { cout<<e.what()<<endl; return -1; } Environment::terminateEnvironment(env); cout<<"end!"<<endl; return 0;}
测试
若没有chr_out[stmt->getInt(3)]='\0';,则最后有乱码
若'\0’赋值的下标不对,则数据被截取
0 0
- 使用OCCI交互CLOB
- c++使用occi 与oracle交互
- occi Clob转换为std::string
- OCCI使用之一
- VC++中使用OCCI
- VC++中使用OCCI
- linux下occi使用
- OCCI
- 在VC++中使用OCCI
- 使用OCCI遇到的几个问题
- 在VC++中使用OCCI
- linux下occi使用问题
- 在VC++中使用OCCI
- vs2005 中使用OCCi链接oracle
- 使用OCCI连接Linux下Oracle数据库
- C# 使用OCCI 连接Oracle 数据库
- vs2010使用occi连接oracle数据库
- vs2010使用occi连接oracle数据库
- [Android]在Adapter的getView方法中绑定OnClickListener比较好的方法
- 创业应随内心,而非其魅力
- [Android]ListView的Adapter.getView()方法中延迟加载图片的优化
- 【MVC类库学习笔记】编写第一个MVC类-配置web.config
- Unix C (一)
- 使用OCCI交互CLOB
- Netty服务器线程模型概览
- 安卓对应的各种支付模式
- UVA - 755 487--3279 sort的使用
- Android Api Component---翻译任务和回退栈(Tasks and Back Stack)
- WebService到底是什么?
- 分治法:归并排序分析
- Java中的匿名内部类
- Linux rpm 命令参数使用详解[介绍和应用]