程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle教程 >> JDBC ORACLE BLOB處理

JDBC ORACLE BLOB處理

編輯:Oracle教程

JDBC ORACLE BLOB處理


LOB,即Large Objects(大對象),是用來存儲大量的二進制和文本數據的一種數據類型(一個LOB字段可存儲可多達4GB的數據)。
LOB 分為兩種類型:內部LOB和外部LOB。
內部LOB將數據以字節流的形式存儲在數據庫的內部。因而,內部LOB的許多操作都可以參與事務,
也可以像處理普通數據一樣對其進行備份和恢復操作。Oracle支持三種類型的內部LOB:
BLOB(二進制數據)
CLOB(單字節字符數據)
NCLOB(多字節字符數據)。
CLOB和NCLOB類型適用於存儲超長的文本數據,BLOB字段適用於存儲大量的二進制數據,如圖像、視頻、音頻,文件等。


目前只支持一種外部LOB類型,即BFILE類型。在數據庫內,該類型僅存儲數據在操作系統中的位置信息,
而數據的實體以外部文件的形式存在於操作系統的文件系統中。因而,該類型所表示的數據是只讀的,不參與事務。
該類型可幫助用戶管理大量的由外部程序訪問的文件.


使用JDBC來寫入Blob型數據到Oracle中 :
Oracle的Blob字段比long字段的性能要好,可以用來保存如圖片之類的二進制數據。
Oracle的BLOB字段由兩部分組成:數據(值)和指向數據的指針(定位器)。盡管值與
表自身一起存儲,但是一個BLOB列並不包含值,僅有它的定位指針。為了使用大對象,程序必須聲明定位器類型的本地變量。
當Oracle內部LOB被創建時,定位器被存放在列中,值被存放在LOB段中,LOB段是在數據庫內部表的一部分。
因為Blob自身有一個cursor,當寫入Blob字段必須使用指針(定位器)對Blob進行操作,因而在寫入Blob之前,
必須獲得指針(定位器)才能進行寫入
如何獲得Blob的指針(定位器) :需要先插入一個empty的blob,這將創建一個blob的指針,然後再把這個empty
的blob的指針查詢出來,這樣通過兩步操作,就獲得了blob的指針,可以真正的寫入blob數據了。
具體步驟:
1、插入空blob insert into javatest(name,content) values(?,empty_blob());


2、獲得blob的cursor select content from javatest where name= ? for update;
注意: 須加for update,鎖定該行,直至該行被修改完畢,保證不產生並發沖突。
3、利用 io,和獲取到的cursor往數據庫寫數據流

案例:以下案例實現插入一張圖片,和獲取有一張圖片的查詢結果;
/*
 * 文件名:BlobTest.java
 * 版權:Copyright by www.huawei.com
 * 描述:
 * 修改人:Cuigaochong
 * 修改時間:2015-8-25
 * 跟蹤單號:
 * 修改單號:
 * 修改內容:
 */

package com.jdbc.cgc.blob;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import oracle.sql.BLOB;

import org.junit.Test;

/**
 * <一句話功能簡述> <功能詳細描述>
 * 
 * @author 姓名 工號
 * @version [版本號, 2015-8-25]
 * @see [相關類/方法]
 * @since [產品/模塊版本]
 */
public class BlobTest
{
    
    /**
     * <一句話功能簡述>測試方法,插入一條數據,數據中有一個列是Blob <功能詳細描述>
     * 
     * @throws FileNotFoundException
     * @see [類、類#方法、類#成員]
     */
    @Test
    public void test00()
        throws FileNotFoundException
    {
        // 注意: 對於empty_blob()應放在SQL語句中直接賦值, 使用預置語句的方式賦值無法實現.
        String sql = "insert into t_emp13(first_name,salary,picture) values (?,?,Empty_BLOB())";
        // 查詢Blob 注意進行 行鎖定 後邊的for update
        String sqlQuery = "select picture from t_emp13 where first_name = ? and salary = ? for update";
        updateBlob(sql, sqlQuery, "QQA122", 1233);
    }
    
    /**
     * <一句話功能簡述>更新有blob的數據庫表 <功能詳細描述>
     * 
     * @param sqlInsert
     * @param sqlQuery
     * @param args
     * @see [類、類#方法、類#成員]
     */
    public void updateBlob(String sqlInsert, String sqlQuery, Object... args)
    {
        Connection conn = null;
        PreparedStatement prepareStatement = null;
        ResultSet rs = null;
        
        OutputStream os = null;
        FileInputStream fis = null;
        try
        {
            // 現在表中插入空的Blob
            conn = getConn();
            // 事物處理前,取消Connection的默認提交行為
            conn.setAutoCommit(false);
            prepareStatement = conn.prepareStatement(sqlInsert);
            
            for (int i = 0; i < args.length; i++)
            {
                prepareStatement.setObject(i + 1, args[i]);
            }
            prepareStatement.executeUpdate();
            
            BLOB blob = null;
            
            prepareStatement = conn.prepareStatement(sqlQuery);
            
            for (int i = 0; i < args.length; i++)
            {
                prepareStatement.setObject(i + 1, args[i]);
            }
            
            // prepareStatement.setString(1, "QQA");
            rs = prepareStatement.executeQuery();
            if (rs.next())
            {
                blob = (BLOB)rs.getBlob(1);
            }
            // 得到數據庫的輸出流
            os = blob.getBinaryOutputStream();
            // 得到要插入文件的輸入流
            fis = new FileInputStream("Tulips.jpg");
            
            byte[] b = new byte[1024];
            int len;
            while (-1 != (len = fis.read(b)))
            {
                os.write(b, 0, len);
            }
            // 清空流的緩存
            os.flush();
            // 事物處理:如果事物處理成功則提交事物
            conn.commit();
        }
        catch (Exception e)
        {
            e.printStackTrace();
            try
            {
                // 事物處理:如果出現異常 則在catch塊中回滾事物
                conn.rollback();
            }
            catch (SQLException e1)
            {
                e1.printStackTrace();
            }
        }
        finally
        {
            if (null != fis)
            {
                try
                {
                    fis.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            if (null != os)
            {
                try
                {
                    os.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            
            releaseSource(prepareStatement, conn, null);
        }
    }
    
    /**
     * <一句話功能簡述>測試方法,查詢有blob的表 <功能詳細描述>
     * 
     * @see [類、類#方法、類#成員]
     */
    @Test
    public void test01()
    {
        String sql = "select picture from t_emp13 where first_name = ?";
        queryBlob(sql, "QQA122");
    }
    
    /**
     * <一句話功能簡述>查詢有Blob的表 方法 <功能詳細描述>
     * 
     * @param sql
     * @param args
     * @see [類、類#方法、類#成員]
     */
    public void queryBlob(String sql, Object... args)
    {
        Connection conn = null;
        PreparedStatement prepareStatement = null;
        ResultSet rs = null;
        
        FileOutputStream fos = null;
        InputStream is = null;
        
        try
        {
            conn = getConn();
            // 事物處理前,取消Connection的默認提交行為
            conn.setAutoCommit(false);
            prepareStatement = conn.prepareStatement(sql);
            for (int i = 0; i < args.length; i++)
            {
                prepareStatement.setObject(i + 1, args[i]);
            }
            rs = prepareStatement.executeQuery();
            if (rs.next())
            {
                BLOB blob = (BLOB)rs.getBlob(1);
                is = blob.getBinaryStream();
                
                fos = new FileOutputStream(new File("test.png"));
                
                byte[] b = new byte[1024];
                int len;
                
                while (-1 != (len = is.read(b)))
                {
                    fos.write(b, 0, len);
                }
                fos.flush();
            }
            // 事物處理:如果事物處理成功則提交事物
            conn.commit();
            
        }
        catch (Exception e)
        {
            e.printStackTrace();
            try
            {
                // 事物處理:如果出現異常 則在catch塊中回滾事物
                conn.rollback();
            }
            catch (SQLException e1)
            {
                e1.printStackTrace();
            }
        }
        finally
        {
            if (null != is)
            {
                try
                {
                    is.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            
            if (null != fos)
            {
                try
                {
                    fos.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            
            releaseSource(prepareStatement, conn, rs);
        }
    }
    
    /**
     * <一句話功能簡述> 連接數據庫 <功能詳細描述>
     * 
     * @return
     * @throws Exception
     * @see [類、類#方法、類#成員]
     */
    public Connection getConn()
        throws Exception
    {
        String dirverName = null;
        String jdbcUrl = null;
        String user = null;
        String password = null;
        
        Properties propertoes = new Properties();
        InputStream is = getClass().getClassLoader().getResourceAsStream("jdbc.properties");
        propertoes.load(is);
        
        dirverName = propertoes.getProperty("driver");
        jdbcUrl = propertoes.getProperty("jdbcURL");
        user = propertoes.getProperty("user");
        password = propertoes.getProperty("password");
        
        Class.forName(dirverName);
        
        // 通過DriverManager的getConnection獲取數據庫連接
        Connection connection = DriverManager.getConnection(jdbcUrl, user, password);
        
        return connection;
    }
    
    /**
     * <一句話功能簡述>釋放數據庫資源 <功能詳細描述>
     * 
     * @param statement
     * @param conn
     * @param resultSet
     * @see [類、類#方法、類#成員]
     */
    public void releaseSource(Statement statement, Connection conn, ResultSet resultSet)
    {
        if (null != resultSet)
        {
            try
            {
                resultSet.close();
            }
            catch (SQLException e)
            {
                e.printStackTrace();
            }
        }
        
        if (null != statement)
        {
            try
            {
                statement.close();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
        if (null != conn)
        {
            try
            {
                conn.close();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved