java oracle数据blob的操作
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java oracle数据blob的操作相关的知识,希望对你有一定的参考价值。
我有个数据库表有blob字段,我想把它用java读出来,然后在放假另一个数据库表的blob字段,请问怎么写,求指导
参考技术A // 下面为一个完整的例子,如果用framework,需要做一定修改写入
public boolean saveWordFile(String filePath)
File file = new
File(filePath);
Connection conn = getConnection();
try
java.sql.Statement st = conn.createStatement();
conn.setAutoCommit(false);
st.execute("insert into table_name
values(1,empty_blob())");
ResultSet rs =
st
.executeQuery("select id,word from table_name where
id=1 for update");
if (rs.next())
BLOB blob
= (BLOB) rs.getBlob("word");
OutputStream outStream =
blob.getBinaryOutputStream();
InputStream fin = new
FileInputStream(file);
byte[] b = new
byte[blob.getBufferSize()];
int len = 0;
while ((len = fin.read(b)) != -1)
outStream.write(b, 0,
len);
fin.close();
outStream.flush();
outStream.close();
conn.commit();
conn.close();
catch (SQLException e)
// TODO Auto-generated catch
block
e.printStackTrace();
catch
(FileNotFoundException e)
// TODO Auto-generated catch
block
e.printStackTrace();
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
return true;
读取
public void getWordFile(String id)
Connection conn =
getConnection();
java.sql.Statement st;
try
st = conn.createStatement();
ResultSet rs =
st.executeQuery("select id,word from table_name where
id='"+id+"'");
if (rs.next())
BLOB blob =
(BLOB) rs.getBlob("word");
File file = new
File("c://filename.doc");
FileOutputStream output = new
FileOutputStream(file);
InputStream input =
blob.getBinaryStream();
byte[] buffer = new
byte[1024];
int i = 0;
while ((i =
input.read(buffer)) != -1)
output.write(buffer, 0,
i);
catch (Exception e)
// TODO Auto-generated catch block
e.printStackTrace();
修改
public void updateblob(String id)
Connection
conn=getConnection();
Statement stem=null;
ResultSet rs=null;
try
conn.setAutoCommit(false);
stem=conn.createStatement();
rs = stem.executeQuery("select word
from table_name where id='"+id+"' for update");
if
(rs.next())
BLOB blob = (BLOB) rs.getBlob("word");
OutputStream outStream = blob.getBinaryOutputStream();
InputStream fin = new FileInputStream("c://2.doc");
byte[] b = new byte[blob.getBufferSize()];
int
len = 0;
while ((len = fin.read(b)) != -1)
outStream.write(b, 0, len);
fin.close();
outStream.flush();
outStream.close();
conn.commit();
conn.close();
catch (Exception ex)
try
conn.rollback();
catch (SQLException e)
// TODO
Auto-generated catch block
e.printStackTrace();
System.out.println(ex.getMessage());
追问
我的是直接表里面读出来又放到另一个表中blob类型的,能直接放吗
追答只能这样处理blob/clob的
SQLAlchemy 在 Oracle DB 中批量插入 blob 数据
【中文标题】SQLAlchemy 在 Oracle DB 中批量插入 blob 数据【英文标题】:SQLAlchemy bulk insert blob data in Oracle DB 【发布时间】:2022-01-20 17:23:50 【问题描述】:我正在尝试使用 Oracle DB 在 SQLAlchemy 中进行批量插入操作,该操作使用 blob 数据插入 60k 行。
这就是我的表格和代码的样子:
CREATE TABLE datatables (
id INTEGER NOT NULL,
table_name VARCHAR2(50 CHAR),
row_id VARCHAR2(50 CHAR),
row_data BLOB,
PRIMARY KEY (id)
)
with Session() as session:
session.execute(
DataTables.__table__.insert(),
datas
)
DataTables
是表的 SQLAclhemy 类映射,datas
是这样的字典列表'id': 1, 'table_name': 'app', 'row_id': 'version', 'row_data': '....'
用这样的代码我得到了这个 sql 语句
sqlalchemy.engine.Engine INSERT INTO datatables (id, table_name, row_id, row_data) VALUES (:id, :table_name, :row_id, :row_data)
sqlalchemy.engine.Engine [generated in 0.14718s] ['id': 1, 'table_name': 'app', 'row_id': 'version', 'row_data': b'some_data', ...]
它会永远运行,即使 30 分钟后它也没有完成。当我启用 DPI 跟踪时,会有很多这样的行:
ODPI [12912] 2021-12-18 00:07:36.019: ref 0000019C3D15C5B0 (dpiConn) -> 8
ODPI [12912] 2021-12-18 00:07:36.020: ref 0000019C413F0C20 (dpiLob) -> 1 [NEW]
ODPI [12912] 2021-12-18 00:07:36.020: ref 0000019C3D15C5B0 (dpiConn) -> 9
ODPI [12912] 2021-12-18 00:07:36.020: ref 0000019C413F1990 (dpiLob) -> 1 [NEW]
但是,如果我使用原始 sql:
session.execute('insert into DATATABLES (id, table_name, row_id, row_data) values (:id, :table_name, :row_id, :row_data)', datas)
DPI 跟踪更改为:
ODPI [00796] 2021-12-18 00:14:55.246: ref 000002486741EAF0 (dpiVar) -> 0
ODPI [00796] 2021-12-18 00:14:55.246: ref 00000248617D2DF0 (dpiConn) -> 6
ODPI [00796] 2021-12-18 00:14:55.246: fn end dpiVar_release(000002486741EAF0) -> 0
ODPI [00796] 2021-12-18 00:14:55.246: fn start dpiVar_setFromBytes(000002486741EBB0)
ODPI [00796] 2021-12-18 00:14:55.247: fn end dpiVar_setFromBytes(000002486741EBB0) -> 0
ODPI [00796] 2021-12-18 00:14:55.247: fn start dpiVar_setFromBytes(0000024864E5FDE0)
ODPI [00796] 2021-12-18 00:14:55.247: fn end dpiVar_setFromBytes(0000024864E5FDE0) -> 0
ODPI [00796] 2021-12-18 00:14:55.247: fn start dpiVar_setFromBytes(0000024864E601A0)
ODPI [00796] 2021-12-18 00:14:55.247: fn end dpiVar_setFromBytes(0000024864E601A0) -> 0
批量插入在 15 秒内完成。
两种情况下的 SQL 语句相同。为什么它的工作方式不同?当然我可以使用原始 sql,但我想使用DataTables.__table__.insert()
,因为如果表或列名称会改变 - 我不需要每次都修复 sql。
【问题讨论】:
使用 Alchemy 进行的最可能解释是您正在逐行插入。激活 10046 跟踪来证明这一点。 10046 跟踪?抱歉,我对oracle调试不是很熟悉 参见例如here 我检查了跟踪 - 它是 executemany,而不是逐行。唯一的区别是当我使用DataTables.__table__.insert()
时它使用dpiLob_setFromBytes
,但使用原始sql 时它是dpiVar_setFromBytes
。不知道为什么它会从 lob 变为 var 以及为什么在这种情况下 lob 会变慢。
在使用 dpiLob_setFromBytes() 的情况下,您正在创建一个临时 LOB,写入它,然后从临时 LOB 传输到永久 LOB。在使用 dpiVar_setFromBytes() 的另一种情况下,数据是直接传输的——正如您所发现的,它的效率要高得多!
【参考方案1】:
最好将此类问题报告为 SQLAlchemy 中的错误,您可以通过以下方式进行报告:https://github.com/sqlalchemy/sqlalchemy/issues/,否则我们完全不知道这个问题。
在这种情况下,我们已收到有关此问题的警报,并将设法为 SQLAlchemy 2.0 的 cx_oracle 开发人员更新我们的 LOB 设置,跟踪地址为 https://github.com/sqlalchemy/sqlalchemy/issues/7494
【讨论】:
说实话,我还以为是我做错了什么,而不是 SQLAlchemy 的错误行为。感谢您报告问题以上是关于java oracle数据blob的操作的主要内容,如果未能解决你的问题,请参考以下文章