%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ include file="/WEB-INF/jsp/include.jsp" %>
Algunas aplicaciones requieren el manejo de documentos. Por ejemplo una Web que gestiona ofertas de trabajo puede solicitar al candidato que cargue (upload) un archivo con su CV y le permite a la empresa ofertante descargarse (download) dicho archivo. Los documentos se almacenan en campos de tipo LOB (Large Object) en nuestra base de datos. Si el campo soporta gran cantidad de datos en modo caracter hablamos de CBLOB y si soporta datos binarios nos refereimos BLOB. Los LOBs son campos que exigen un tratamiento especial en JDBC y por tanto en Spring.
Spring exige
En nuestro DAO tendremos:
import com.persistencia.query.ImagenSetter;
import org.springframework.jdbc.support.lob.LobHandler;
import org.springframework.jdbc.support.lob.DefaultLobHandler;
import java.io.IOException;
import java.io.InputStream;
...
public void insertarImagen(Integer id, final InputStream in) throws IOException {
LobHandler lobHandler = new DefaultLobHandler();
getJdbcTemplate().execute( "INSERT INTO cliente (id, imagen) VALUES (?, ?)",
new ImagenSetter(lobHandler, id, in) );
}
...
Nuestra clase ImagenSetter hereda de AbstractLobCreatingPreparedStatementCallback:
import org.springframework.jdbc.core.support.AbstractLobCreatingPreparedStatementCallback;
import org.springframework.jdbc.support.lob.LobHandler;
import org.springframework.jdbc.support.lob.LobCreator;
import java.io.IOException;
import org.springframework.dao.DataAccessException;
import java.io.InputStream;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class ImagenSetter extends AbstractLobCreatingPreparedStatementCallback {
int tamanioImagen;
Integer id;
InputStream in;
public ImagenSetter(LobHandler lobHandler, final Integer id, final InputStream in) throws IOException {
super(lobHandler);
tamanioImagen = in.available();
this.in = in;
this.id = id;
}
protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException, DataAccessException {
ps.setInt(1, id);
lobCreator.setBlobAsBinaryStream(ps, 2, in, tamanioImagen);
}
}
El método setValues() ya lo hemos visto como la solución Spring para trabajar con PreparedStatement. Es un método CallBack, es decir, será llamado por Spring, no por nuestra aplicación, cuando sea necesario inyectar los parámetros en la sentencia INSERT:
Argumentos de setBlobAsBinaryStream:
public void getImagen(Integer id, final OutputStream out) {
getJdbcTemplate().query("SELECT image FROM member_image WHERE id = ?",
new AbstractLobStreamingResultSetExtractor() {
protected void streamData(ResultSet rs) throws SQLException, IOException {
FileCopyUtils.copy(lobHandler.getBlobAsBinaryStream(rs, 1), out);
}
}
);
}