TestMsSqlImage

来源:互联网 发布:阿里云服务器托管合同 编辑:程序博客网 时间:2024/06/11 05:33
package com.jasonhuang.test;

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

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

/*
 * 测试利用 SQL Server 的 Image 类型存储文件,并从数据库取出数据存入文件
 * 数据库表:
 *  T1_TB_TestFile
 * 字段:
 *  [FileUUID] [char](36) NOT NULL
 *  [FileContent] [image] NULL
 
*/

public class TestMsSqlImage {

    
// Log4j Logger
    private static Logger logger = Logger.getLogger(TestMsSqlImage.class);

    
// 数据库JDBC常量
    private static String JDBC_DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";

    
private static String JDBC_URL = "jdbc:sqlserver://HOME-AMD";

    
private static String MSSQL_DATABASE = "test1";

    
private static String MSSQL_USER = "sa";

    
private static String MSSQL_PASSWORD = "123";

    
// 存入数据库的文件路径
    private static String INPUT_FILE = "C:/Temp/生物课件.zip";

    
// 从数据库取出的文件路径
    private static String OUTPUT_FILE = "C:/Temp/OUT.zip";

    
/**
     * 文件 -> 数据库 -> 文件
     * 
     * 
@param args
     
*/

    
public static void main(String[] args) {
        logger.setLevel(Level.ALL);

        Connection conn 
= null;
        Statement stmt 
= null;
        PreparedStatement pstmt 
= null;
        ResultSet rs 
= null;
        String sql 
= null;
        FileInputStream input 
= null;
        FileOutputStream output 
= null;

        
try {
            
// 设置数据库属性
            Properties properties = new Properties();
            properties.setProperty(
"database", MSSQL_DATABASE);
            properties.setProperty(
"user", MSSQL_USER);
            properties.setProperty(
"password", MSSQL_PASSWORD);

            
// 传统JDBC获得连接
            Class.forName(JDBC_DRIVER);
            conn 
= DriverManager.getConnection(JDBC_URL, properties);
            stmt 
= conn.createStatement();

            
// 随机获得唯一UUID
            String uuid = UUID.randomUUID().toString();
            
// 生成一条数据库数据
            sql = "insert into T1_TB_TestFile (FileUUID) values ('" + uuid
                    
+ "')";
            stmt.executeUpdate(sql);

            
// 即使在insert时插入image类型的值为null,数据库依然不会创建指针。可以使用update创建指针。
            sql = "update T1_TB_TestFile set FileContent = null where FileUUID = '"
                    
+ uuid + "'";
            stmt.executeUpdate(sql);

            
// 创建缓冲区,微软建议最佳长度为8040的倍数
            int length = 8040 * 100;
            
byte[] buffer = new byte[length];
            
// Image 类型的指针
            byte[] ptr = null;
            
// 偏移量
            int offset = 0;
            
// 读写字节数
            int len = 0;
            
// 文件长度
            long size = 0;

            File file 
= null;

            
// 取消 Auto Commit
            conn.setAutoCommit(false);

            
// 获得 Image 类型的指针
            sql = "select textptr(FileContent) from T1_TB_TestFile where FileUUID = '"
                    
+ uuid + "'";
            rs 
= stmt.executeQuery(sql);
            
if (rs.next()) {
                ptr 
= rs.getBytes(1);
            }

            rs.close();
            rs 
= null;

            
if (ptr != null{

                
// 获得文件输入流
                file = new File(INPUT_FILE);
                logger.info(
"磁盘上原始的文件长度为: " + file.length());
                input 
= new FileInputStream(file);

                
// 更新 Image 类型字段,0表示不删除内容
                sql = "updatetext T1_TB_TestFile.FileContent ? ? 0 ?";
                pstmt 
= conn.prepareStatement(sql);
                
// 读取input流,-1表示已经读完
                while ((len = input.read(buffer)) != -1{
                    
// Image 类型的指针
                    pstmt.setBytes(1, ptr);
                    
// 偏移量
                    pstmt.setInt(2, offset);
                    
// 写入的内容
                    pstmt.setBytes(3, buffer);
                    
// 将读取内容写入数据库
                    pstmt.executeUpdate();
                    
// 清空参数
                    pstmt.clearParameters();
                    
// 移动偏移量
                    offset += len;
                }

                pstmt.close();
                pstmt 
= null;

                
// 关闭输入流
                input.close();
                input 
= null;

                
// 删除多余内容,NULL 表示删除偏移量后所有内容
                sql = "updatetext T1_TB_TestFile.FileContent ? ? NULL";
                pstmt 
= conn.prepareStatement(sql);
                pstmt.setBytes(
1, ptr);
                pstmt.setInt(
2, offset);
                pstmt.executeUpdate();
                pstmt.close();
                pstmt 
= null;

                ptr 
= null;
            }

            
// Commit Connection
            conn.commit();

            
// 获得文件长度
            sql = "select datalength(filecontent) from T1_TB_TestFile where FileUUID = '"
                    
+ uuid + "'";
            rs 
= stmt.executeQuery(sql);
            
if (rs.next()) {
                size 
= rs.getLong(1);
                logger.info(
"数据库写入的文件长度为: " + size);
            }


            
// 获得 Image 类型的指针
            sql = "select textptr(FileContent) from T1_TB_TestFile where FileUUID = '"
                    
+ uuid + "'";
            rs 
= stmt.executeQuery(sql);
            
if (rs.next()) {
                ptr 
= rs.getBytes(1);
            }

            rs.close();
            rs 
= null;

            
if (ptr != null{

                
// 获得文件输出流
                file = new File(OUTPUT_FILE);
                
if (file.exists()) {
                    file.delete();
                }

                output 
= new FileOutputStream(file);

                
// 偏移量置零
                offset = 0;
                
// 读取 Image 类型字段,holdlock表示锁定以进行读取,直到事务结束为止。
                sql = "readtext T1_TB_TestFile.FileContent ? ? ? holdlock";
                pstmt 
= conn.prepareStatement(sql);
                
// 写入output流,<=表示已经写完
                while (size > 0{
                    
// Image 类型的指针
                    pstmt.setBytes(1, ptr);
                    
// 偏移量
                    pstmt.setInt(2, offset);
                    
// 读出的长度
                    len = length < size ? length : (int) size;
                    pstmt.setInt(
3, len);
                    
// 将内容读出数据库
                    rs = pstmt.executeQuery();

                    
if (rs.next()) {
                        buffer 
= rs.getBytes(1);
                        output.write(buffer);
                    }


                    
// 清空参数
                    pstmt.clearParameters();
                    
// 移动偏移量
                    offset += len;
                    size 
-= len;
                }

                pstmt.close();
                pstmt 
= null;

                
// 关闭输出流
                output.close();
                output 
= null;
                logger.info(
"数据库读出的文件长度为: " + file.length());
            }


            
// Commit Connection
            conn.commit();
            conn.close();
            conn 
= null;
        }
 catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
 finally {
            
// 依次关闭资源
            if (rs != null{
                
try {
                    rs.close();
                }
 catch (SQLException e) {
                    logger.error(e.getMessage(), e);
                }

                rs 
= null;
            }

            
if (stmt != null{
                
try {
                    stmt.close();
                }
 catch (SQLException e) {
                    logger.error(e.getMessage(), e);
                }

                stmt 
= null;
            }

            
if (pstmt != null{
                
try {
                    pstmt.close();
                }
 catch (SQLException e) {
                    logger.error(e.getMessage(), e);
                }

                pstmt 
= null;
            }

            
if (conn != null{
                
try {
                    conn.rollback();
                    conn.close();
                }
 catch (SQLException e) {
                    logger.error(e.getMessage(), e);
                }

                conn 
= null;
            }

            
if (input != null{
                
try {
                    input.close();
                }
 catch (IOException e) {
                    logger.error(e.getMessage(), e);
                }

                input 
= null;
            }

            
if (output != null{
                
try {
                    output.close();
                }
 catch (IOException e) {
                    logger.error(e.getMessage(), e);
                }

                output 
= null;
            }

        }

    }

}