目1 引言
本文档的编写是为了解决在集成过程中经常遇到的Clob类型的集成问题。这里是通过编写Jython代码,将代码嵌入到KM中,实现Clob类型数据的抽取。
缩写、术语 |
解 释 |
Clob |
Character Large Object,字符型大对象,主要用于存储内容较长的文本。 |
与Blob的类似,在LKM sql to sql (Jython)中并未指定对Clob的处理方法。所以,我们同样需要将对Clob的处理方式加入到Jython代码中。
同样,与Blob的处理方式类似,对Clob同样需要先转化为流——字符流。在java中,Clob是这样进行处理的:
getCharacterStream(int columnIndex)
setCharacterStream(int parameterIndex,Reader reader,Int length)
总的处理思路还是与Blob类似:
1. 将Clob数据以字符流的形式读出。
2. 判断读出的Clob是否为空,如果为空,则直接以setCharacterStream输出,length指定为0。如果非空,则将字节流读入到一个缓冲数组,再将缓冲数组读入到一个输出流中,获取输出流的长度(转为字符数组可得到长度),然后就可以通过set方法将输出流写入临时区域的Clob字段。
虽然处理的思路相同,但引用的方法却不同,这点将在接下来介绍。
另外,Clob和Blob一样,都不能进行“==”比较和在minus、distinct、group by等子句中出现,所以同样要用到IKM Oracle Incremental Update Lob,这个KM中是删除了minus操作的。
我们先在ODI中打开LKM sql to sql(Jython),双击打开步骤Load data (JYTHON),
同样,加入一段elif代码,如图:
加入的代码如下:
elif colType == sql.Types.CLOB: #Code 2001
resline=rqteSrc.getCharacterStream(nb+1)
if resline:
ary = jarray.zeros(1024,'c')
r = resline.read(ary)
out = CharArrayWriter()
while (r >= 0) :
out.write(ary,0,r)
r = resline.read(ary)
try:
instream = CharArrayReader(out.toCharArray())
length = len(out.toCharArray())
psmt.setCharacterStream(nb+1,instream,length)
except java.lang.Exception,e:
print e.getLocalizedMessage().encode("utf-8")
elif not resline:
psmt.setCharacterStream(nb+1,resline,0)
现在来分析这段代码,
1. resline=rqteSrc.getCharacterStream(nb+1),这是对字符流的处理方式,与字节流不同。
2. ary = jarray.zeros(1024,'c'),这里是‘c’,不是Blob用的‘b’。
3. out = CharArrayWriter(),这是生成字符输出流的方式,有别于Blob的out = ByteArrayOutputStream()
4. instream = CharArrayReader(out.toCharArray()),生成字符输入流。
5. out.toCharArray()生成字符数组,Blob中是out.toByteArray()。
这段代码可对照Blob的处理代码来看,也可对照文档《Blob类型的集成》来看。
引用的包有:
from java.io import CharArrayWriter
from java.io import CharArrayReader
最后,将LKM保存并重命名为LKM sql to sql Clob(Jython)。
我们先在ODI中打开LKM sql to sql(Jython),双击打开步骤Load data (JYTHON),
打开它的表达式编辑器,查看它的代码,可以看到一些诸如如下代码的语句
elif colType == sql.Types.CHAR:
resline=rqteSrc.getString(nb+1)
psmt.setString(nb+1,resline)
这些语句的功能是对针对不同的数据类型采取不一样的类型判断。因此,我们在改写这个KM时,只需要将处理Blob类型的语句加入其中就可以实现对Blob的读取了。
因此,在这些elif语句中,加入了一行新的elif,如图:
加入的代码如下:
elif colType == sql.Types.BLOB: #Code 2000
resline=rqteSrc.getBinaryStream(nb+1)
if resline:
buffer = jarray.zeros(1024,'b')
r = resline.read(buffer)
out = ByteArrayOutputStream()
while (r >= 0) :
out.write(buffer,0,r)
r = resline.read(buffer)
try:
instream = ByteArrayInputStream(out.toByteArray())
length = len(out.toByteArray())
psmt.setBinaryStream(nb+1,instream,length)
except java.lang.Exception,e:
print e.getLocalizedMessage().encode("utf-8")
elif not resline:
psmt.setBinaryStream(nb+1,resline,0)
这里的语法采用的是Jython的语法,Jython语言与其它语言有些不同,它不以分号来标识一行代码的结束,只用换行就可以,另外,Jython使用空格缩进,来识别程序的分组和级别,例如上面的代码中,第三行的if和倒数第二行的elif,他们的起始符都是用了6个空格缩进,这样Jython才能识别这个if和elif属于同一分组,这点非常重要。
现在来分析这段代码,
1. elif colType == sql.Types.BLOB,判断字段类型是否为Blob;
2. resline=rqteSrc.getBinaryStream(nb+1),将数据以字节流的方式读出,代码最后的psmt.setBinaryStream(nb+1,instream,length)表示将instream写入目标。
3. if resline表示判断resline是否为空,buffer = jarray.zeros(1024,'b')表示创建一个buffer数组,‘b’代表存储的是字节型,1024是数组长度(1KB)。
4. r = resline.read(buffer)将resline写入buffer数组,r表示读入的字节数。
5. out = ByteArrayOutputStream()
while (r >= 0) :
out.write(buffer,0,r)
r = resline.read(buffer)
这段生成一个out输出流。实际上,将resline读入out中,每次都是读1KB,直至读完为止,while语句的功能就是如此,当r为null时,停止循环。
6. instream = ByteArrayOutputStream (out.toByteArray())表示将out生成一个输入流。
7. length = len(out.toByteArray())表示获取输出流out的长度,也就是Blob字段的大小。
8. elif not resline表示当resline为null时怎么处理。判断resline是否为null一定要加入代码,不然,一味用ByteArrayOutputStream和ByteArrayOutputStream的方法处理,会导致在执行r = resline.read(buffer)时报错。
因为在这段Jython代码中引用了一些java的方法,因此在代码最开始的部分,要将这些包import进来。所以最开始要加入如下代码:
import jarray
from java.io import ByteArrayOutputStream
from java.io import ByteArrayInputStream
此IKM与Blob集成所用的IKM一样,都是采用的IKM Oracle Incremental Update Lob(删除了minus操作)。做实施时,可以将此KM导入即可。
创建接口INT_CLOB_ORA_TO_ORA,实现Clob数据从Oracle到Oracle的集成。
在“流”标签页中选择编辑好的KM:
“确定”,完成接口的创建。
执行接口,在Operator中查看,
LKM sql to sql Clob(Jython)用于处理Oracle的Clob字段。如果是其他数据库的字符型大对象字段,例如SQL Server的text、ntext类型,可以采用相同的处理思想来实现数据的加载——即转为字符流来判断字段长度,并将数据读出。
IKM Oracle Incremental Update Lob也仅适用于Oracle的Lob集成,其他数据库的集成时所需的IKM还需要重新编辑。
LKM sql to sql Clob(Jython)和IKM Oracle Incremental Update Lob都已放置在配置库中,在实施中可直接导入ODI中使用。