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的操作的主要内容,如果未能解决你的问题,请参考以下文章

如何在java中读取oracle blob

java 怎么读取oracle的blob类型数据,我的是保存新闻内容! 只有这么多财富值了,帮个忙谢谢

java读取blob全身乱码

oracle中如何实现blob和base64相互转换

Oracle中Blob和Clob

使用 Java 为 DB2 和 Oracle 插入 BLOB