Package com.alexkasko.springjdbc.blob

Source Code of com.alexkasko.springjdbc.blob.TempFileJdbcBlobTool

package com.alexkasko.springjdbc.blob;

import com.alexkasko.springjdbc.compress.Compressor;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterUtils;
import org.springframework.jdbc.core.namedparam.ParsedSql;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;

/**
* Client-side implementation of BLOB tool for databases, that don't support
* {@code java.io.OutputStream java.sql.Blob#setBinaryStream(long pos)} method properly
* (implement it on client in-memory or in similar fashion with temp file).
* This implementation creates BLOB as compressed temp file and transfer data from it after BLOB closed by client.
* Data is inserted from file into database using JDBC's streaming
* {@code void java.sql.PreparedStatement#setBinaryStream(int parameterIndex, java.io.InputStream x, long length)}
* method. So file data never goes fully into memory outside of JDBC driver,
* but may go into memory inside some creepy JDBC implementation.
* Not well suited for highload applications, may be used with H2 database to simulate PostgreSQL-like BLOBs in tests.
*
* @author alexkasko
* Date: 4/27/12
*/
public class TempFileJdbcBlobTool extends AbstractJdbcBlobTool {

    /**
     * Shortcut constructor with default SQL
     *
     * @param dataSource data source
     * @param compressor compressor
     */
    public TempFileJdbcBlobTool(DataSource dataSource, Compressor compressor) {
        super(dataSource, compressor);
    }

    /**
     * @param dataSource    data source
     * @param compressor    compressor
     * @param generateIdSQL SQL to generate BLOB ID, default: {@code select nextval('blob_storage_id_seq')}
     * @param insertSQL     SQL to insert blob into database, default: {@code insert into blob_storage(id, data) values(:id, :data)}
     * @param loadSQL       SQL to load blob data from database, default: {@code select data from blob_storage where id = :id}
     * @param deleteSQL     SQL to delete BLOB from database, default: {@code delete from blob_storage where id = :id}
     */
    public TempFileJdbcBlobTool(DataSource dataSource, Compressor compressor, String generateIdSQL, String insertSQL, String loadSQL, String deleteSQL) {
        super(dataSource, compressor, generateIdSQL, insertSQL, loadSQL, deleteSQL);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public OutputStreamBlob create() throws BlobException {
        try {
            long id = jt.getJdbcOperations().queryForLong(generateIdSQL);
            return new TempFileOutputStreamBlob(id, compressor, new Persister());
        } catch (Exception e) {
            throw e instanceof BlobException ? (BlobException) e : new BlobException("Cannot create blob", e);
        }
    }

    private class Persister implements OnClosePersister {

        @Override
        public void persist(long id, InputStream data, long dataLength) {
            jt.getJdbcOperations().update(new InsertPS(id, data, dataLength));
        }

        private class InsertPS implements PreparedStatementCreator {
            private final long id;
            private final InputStream data;
            private final long length;

            private InsertPS(long id, InputStream data, long length) {
                this.id = id;
                this.data = data;
                this.length = length;
            }

            @Override
            public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
                // substitute named params, see NamedParameterJdbcTemplate#getPreparedStatementCreator(String sql, SqlParameterSource paramSource)
                ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(insertSQL);
                MapSqlParameterSource paramSource = new MapSqlParameterSource();
                paramSource.addValue("id", id, Types.BIGINT);
                paramSource.addValue("data", data, Types.BLOB);
                String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource);
            Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null);
                PreparedStatement stmt = con.prepareStatement(sqlToUse);
                stmt.setLong(1, (Long) params[0]);
                if(length < Integer.MAX_VALUE) {
                    stmt.setBinaryStream(2, (InputStream) params[1], (int) length);
                } else {
                    //warn: JTDS doesn't support long sized blobs
                    stmt.setBinaryStream(2, (InputStream) params[1], length);
                }
                return stmt;
            }
        }
    }
}
TOP

Related Classes of com.alexkasko.springjdbc.blob.TempFileJdbcBlobTool

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.