请问关于Java执行Oracle存储过程时参数为BLOB的问题!
关于参数为BLOB的存储过程如下:
--添加客户信息
procedure addCustomer(--客户姓名
v_customer_name IN CUSTOMER.NAME%TYPE,
...
v_photo IN OUT CUSTOMER.PHOTO%TYPE,
--客户照片
...
v_id OUT CUSTOMER.ID%TYPE
--客户ID
)
IS
v_char_id customer.ID%TYPE;
v_blob_photo customer.photo%TYPE;
...
BEGIN
--生成ID
SELECT SYS_GUID() INTO v_char_id FROM DUAL;
INSERT INTO CUSTOMER
(ID,
CUSTOMER_NAME,
...
PHOTO,
...)
VALUES
(v_char_id,
v_customer_name,
...
EMPTY_BLOB(), //先插入空BLOB
...
);
IF (v_photo IS NOT NULL) THEN
SELECT PHOTO
INTO v_blob_photo
FROM CUSTOMER
WHERE CUSTOMER.ID = v_char_id
FOR UPDATE;
DBMS_LOB.OPEN(v_photo, DBMS_LOB.lob_readonly); --打开DBMS_LOB()包
DBMS_LOB.OPEN(v_blob_photo, DBMS_LOB.lob_readwrite);
DBMS_LOB.append(v_blob_photo, v_photo); --追加要插入的照片到指定位置
DBMS_LOB.close(v_photo);
DBMS_LOB.close(v_blob_photo);
END IF;
SELECT v_char_id INTO v_id FROM DUAL;
COMMIT;
=================================
以上省略部分与此问题无关的代码,存储过程已编译通过,如有问题请指正。
问题是Java部分,如何操作BLOB部分的代码?
Connection conn = null;
OracleResultSet ors = null;
OraclePreparedStatement opst = null;
aCustomer.blobPhoto.putBytes(1, photoBytes); // 抛异常
oProc = (OracleCallableStatement) conn.prepareCall( "{call addCustomer(?,..?)} ");
oProc.setBLOB(1, aCustomer.blobPhoto);
aCustomer.blobPhoto是BLOB类型,photoBytes是图片的字符流,想通过putBytes方法保存BLOB,作为参数传入存储过程,
抛出异常是: 空二进制大对象操作无效
上网查了一下,没有找到类似问题的解决方法。
请问有经验的朋友这种情况下存储过程和Java部分应该如何写?先谢谢了。
[解决办法]
帮你查的,看看
一般来说,大对象存储是把文件存到数据库中,当然也可以内存中的超大字符串。对于象图片这样的文件当然是用二进制存储,这里有很多误区,网络上的教程99%都是行不通的,连SUN自己的文档都一直错误,虽然错误很小。按说二进制文件应该存为BLOB类型,但JBDC2并不能直接对BLOB存入二进制文件,如果你这样做,会得到一个IO而不是SQL异常,为此花了我近两个小时才弄清楚。
如果要把一个二制文件存入ORACLE,用标准的JDBC你就要用LONG ROW类型:
create table tb_file(name varchar(20),detail long row);
然后
File file = new File( "aaa.gif ");
int fileLength =(int) file.length();
InputStream fin = new FileInputStream(file);
PreparedStatement pstmt = con.prepareStatement( "insert into tb_file values( 'aaa.gif ',?) ");
pstmt.setBinaryStream (1, fin, fileLength);
pstmt.executeUpdate();
如果你一定要用BLOB存储,你就必须用ORACLE自己的方法:
create table tb_file(name varchar(20),detail BLOB);
con.setAutoCommit(false);
stmt.executeUpdate( "insert into tb_file values( 'aaa.gif ',empty_blob()) ");
下面必须SELECT得到BLOB的对象再向里写:
rs = stmt.executeQuery( "select detail from tb_file where name= 'aaa.gif ' for upfdate " );
if(rs.next())
{
Blob blob = rs.getBlob(1);
BinaryOutputStream out = ((oracle.sql.BLOB)blob).getBinaryOutputStream();
byte[] b = new byte[((oracle.sql.BLOB)blob).getBufferSize];
InputStream fin = new FileInputStream(file);
int len = 0;
while( (len = fin.read(b)) != -1)
out.write(b,0,len);
fin.close();
out.close();
con.commit();
}
同样读取数据你并不能象LONG ROW那样
InputStream in = rs.getBinaryInputStream( "detail ");
而要
Blob blob = rs.getBlob( "detail ");
in = blob.getBinaryStream();
以上是转贴的一个关于大数据存储的方法
