package org.springframework.samples.imagedb;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.LobRetrievalFailureException;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;
import org.springframework.jdbc.core.support.AbstractLobCreatingPreparedStatementCallback;
import org.springframework.jdbc.core.support.AbstractLobStreamingResultSetExtractor;
import org.springframework.jdbc.support.lob.LobCreator;
import org.springframework.jdbc.support.lob.LobHandler;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
/**
* Default implementation of the central image database business interface.
*
* <p>Uses JDBC with a LobHandler to retrieve and store image data.
* Illustrates direct use of the <code>jdbc.core</code> package,
* i.e. JdbcTemplate, rather than operation objects from the
* <code>jdbc.object</code> package.
*
* @author Juergen Hoeller
* @since 07.01.2004
* @see org.springframework.jdbc.core.JdbcTemplate
* @see org.springframework.jdbc.support.lob.LobHandler
*/
public class DefaultImageDatabase extends SimpleJdbcDaoSupport implements ImageDatabase {
private LobHandler lobHandler;
/**
* Set the LobHandler to use for BLOB/CLOB access.
* Could use a DefaultLobHandler instance as default,
* but relies on a specified LobHandler here.
* @see org.springframework.jdbc.support.lob.DefaultLobHandler
*/
public void setLobHandler(LobHandler lobHandler) {
this.lobHandler = lobHandler;
}
@Transactional(readOnly=true)
public List<ImageDescriptor> getImages() throws DataAccessException {
return getSimpleJdbcTemplate().query(
"SELECT image_name, description FROM imagedb",
new ParameterizedRowMapper<ImageDescriptor>() {
public ImageDescriptor mapRow(ResultSet rs, int rowNum) throws SQLException {
String name = rs.getString(1);
String description = lobHandler.getClobAsString(rs, 2);
return new ImageDescriptor(name, description);
}
});
}
@Transactional(readOnly=true)
public void streamImage(final String name, final OutputStream contentStream) throws DataAccessException {
getJdbcTemplate().query(
"SELECT content FROM imagedb WHERE image_name=?", new Object[] {name},
new AbstractLobStreamingResultSetExtractor() {
protected void handleNoRowFound() throws LobRetrievalFailureException {
throw new EmptyResultDataAccessException(
"Image with name '" + name + "' not found in database", 1);
}
public void streamData(ResultSet rs) throws SQLException, IOException {
InputStream is = lobHandler.getBlobAsBinaryStream(rs, 1);
if (is != null) {
FileCopyUtils.copy(is, contentStream);
}
}
}
);
}
@Transactional
public void storeImage(
final String name, final InputStream contentStream, final int contentLength, final String description)
throws DataAccessException {
getJdbcTemplate().execute(
"INSERT INTO imagedb (image_name, content, description) VALUES (?, ?, ?)",
new AbstractLobCreatingPreparedStatementCallback(this.lobHandler) {
protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException {
ps.setString(1, name);
lobCreator.setBlobAsBinaryStream(ps, 2, contentStream, contentLength);
lobCreator.setClobAsString(ps, 3, description);
}
}
);
}
public void checkImages() {
// Could implement consistency check here...
logger.info("Checking images: not implemented but invoked by scheduling");
}
@Transactional
public void clearDatabase() throws DataAccessException {
getJdbcTemplate().update("DELETE FROM imagedb");
}
}