Java IOException:流已关闭Hibernate MS SQL JDBC4
在获取二进制流时,我收到以下异常Java IOException:流已关闭Hibernate MS SQL JDBC4,java,sql-server-2008,jdbc,stream,hibernate-mapping,Java,Sql Server 2008,Jdbc,Stream,Hibernate Mapping,在获取二进制流时,我收到以下异常 java.io.IOException: The stream is closed. at com.microsoft.sqlserver.jdbc.BaseInputStream.checkClosed(SimpleInputStream.java:93) at com.microsoft.sqlserver.jdbc.PLPInputStream.read(PLPInputStream.java:237) at au.gov.vic.doi.tp.s
java.io.IOException: The stream is closed.
at com.microsoft.sqlserver.jdbc.BaseInputStream.checkClosed(SimpleInputStream.java:93)
at com.microsoft.sqlserver.jdbc.PLPInputStream.read(PLPInputStream.java:237)
at au.gov.vic.doi.tp.service.binary.dao.BinaryDAOImplTest.retrieveBinary(BinaryDAOImplTest.java:102)
我使用的是:Hibernate 4.1.1、MS SQL Server 2008和最新的MS SQL JDBC4驱动程序。
我使用以下自定义映射类型“BlobToStreamUserType”将SQL Blob varcharmax映射到InputStream。Hibernate似乎没有提供将SQL BLOB映射到Java InputStream的类型,MaterializedBlob类型仅将SQL BLOB映射到Java字节[]
我使用'rs.getBinaryStream'返回一个真正的二进制流,而不是内存中缓冲的流,原因是我们有大量的图像,如果多个用户同时访问,将导致内存问题
据微软称
Microsoft驱动程序遵循关于getBinaryStream=>JDBC规范
注意:在获取任何>其他列的值之前,必须读取返回流中的所有数据。对getter方法的下一次调用隐式关闭流。此外,当调用方法InputStream.available时,无论是否有数据>可用,stream>都可能返回0
因此getBinaryStream被设计为返回一个真正的字节流。我们返回一个未在内存中缓冲的真正字节流>,它是一个从服务器响应中直接读取的流>。在获取实现的所有>字节之前,无法关闭contentDataResultSet
我已经尝试将hibernate属性“hibernate.jdbc.use_streams_for_binary”设置为true和false,但是这没有什么区别
这是我的密码:
显示到自定义用户类型的映射的图像实体类
import java.io.InputStream;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;
import com.google.common.base.Objects;
@Entity
@DynamicInsert(false)
@DynamicUpdate(false)
@Table(name = "Binary")
public class Binary
{
.........
@Lob
@Column(name = "image")
@Type(type = "my.package.BlobToStreamUserType")
public InputStream getImageStream()
{
return this.imageStream;
}
}
以下是我的自定义映射类型:
public class BlobToStreamUserType implements UserType
{
public int[] sqlTypes()
{
return new int[]
{ Types.BLOB };
}
public Class returnedClass()
{
return InputStream.class;
}
public Object nullSafeGet(final ResultSet rs, final String[] names, final SessionImplementor session,
final Object owner) throws HibernateException, SQLException
{
return rs.getBinaryStream(names[0]);
}
public void nullSafeSet(final PreparedStatement st, final Object value, final int index,
final SessionImplementor session) throws HibernateException, SQLException
{
if (value != null)
{
if (!InputStream.class.isAssignableFrom(value.getClass()))
{
throw new HibernateException(value.getClass().toString() + " cannot be cast to a java.IO.InputStream");
}
InputStream inStream = (InputStream) value;
st.setBinaryStream(index, inStream);
}
else
{
st.setBytes(index, null);
}
}
public boolean equals(final Object x, final Object y) throws HibernateException
{
return ObjectUtils.equals(x, y);
}
public int hashCode(final Object x) throws HibernateException
{
assert (x != null);
return x.hashCode();
}
public Object deepCopy(final Object value) throws HibernateException
{
return value;
}
public boolean isMutable()
{
return false;
}
public Object replace(final Object original, final Object target, final Object owner) throws HibernateException
{
return original;
}
public Serializable disassemble(final Object value) throws HibernateException
{
//disassemble() is only called when caching the data in the second-level cache
// also safe for mutable objects
throw new UnsupportedOperationException("Not supported yet.");
}
public Object assemble(final Serializable cached, final Object owner) throws HibernateException
{
throw new UnsupportedOperationException("Not supported yet.");
}
}
这是我用来检索图像流的DAO
public class BinaryDAOImpl extends AbstractSpringHibernateDAO implements BinaryDAO
{
public Binary getBinary(final String amsAssetId, final String assetMaintainer, final String variant,
final Integer sequence) throws GetException
{
try
{
Query query = super.getSession().createQuery(
"from Binary bin where bin.amsAssetId = :amsAssetId and bin.assetMaintainer = :assetMaintainer "
+ "and bin.variant = :variant and bin.sequence = :sequence");
query.setParameter("amsAssetId", amsAssetId);
query.setParameter("assetMaintainer", assetMaintainer);
query.setParameter("variant", variant);
query.setParameter("sequence", sequence);
return query.uniqueResult();
}
注意:以下绕过hibernate并直接从结果集中检索流的解决方法可以工作,并且允许我毫无例外地读取流。然而,我宁愿使用hibernate映射来检索真正的二进制流
改进的DAO方法
public Binary getBinary(final String amsAssetId, final String assetMaintainer, final String variant,
final Integer sequence) throws GetException
{
try
{
Query query = super.getSession().createQuery(
"from Binary bin where bin.amsAssetId = :amsAssetId and bin.assetMaintainer = :assetMaintainer "
+ "and bin.variant = :variant and bin.sequence = :sequence");
query.setParameter("amsAssetId", amsAssetId);
query.setParameter("assetMaintainer", assetMaintainer);
query.setParameter("variant", variant);
query.setParameter("sequence", sequence);
Binary binary = (Binary) query.uniqueResult();
final String id = binary.getId();
// Necessary until Hibernate supports InputStream mapping
binary.setImageStream(getSession().doReturningWork(new ReturningWork<InputStream>()
{
public InputStream execute(final Connection connection) throws SQLException
{
PreparedStatement statement = connection.prepareStatement("select image from Binary where id=?",
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
statement.setString(1, id);
ResultSet resultSet = statement.executeQuery();
return (resultSet.first() ? resultSet.getBinaryStream(1) : null);
}
}));
return binary;
}
您是否尝试过将该类型标记为Lob
@Lob
@Column(name = "image")
@Type(type = "my.package.BlobToStreamUserType")
Blob blob;
public Blob getBlob(){
return blob;
}
什么时候你需要使用流
final InputStream is;
try {
is = blob.getBinaryStream();
//do some work
}
如果你知道你可以简单地找回一个斑点,那会很有帮助
在定义自己的类型之前