`
gavin
  • 浏览: 83266 次
  • 性别: Icon_minigender_1
文章分类
社区版块
存档分类
最新评论

hibernate save blob with inputstream

 
阅读更多
hibernate 保存blob字段,映射为byte[]正常,映射为Blob或InputStream则报SQL语法错误
 @Lob
 @Type(type="com.xxx.common.entity.BlobUserType")
 private InputStream data;

跟踪发现PreparedStatement的charEncoding为“GBK”。
检查了表,库和spring配置里都设置了"UTF-8",最后发现是mysql配置文件character_set_server没配置。
是通过以下SQL发现问题,参考
mysql> show variables like 'char%';
mysql> show variables like 'collation%';

有段时间没写java了,觉的还是写JS省事。
hibernate4字段映射为InputStream很多自定义UserType都是很久以前的法,找到一个可用的却因为前面的问题没成功,自己仿造了个新的。
public class BlobUserType extends AbstractSingleColumnStandardBasicType<InputStream> {
    public static final BlobUserType INSTANCE = new BlobUserType();

    public BlobUserType() {
        super( BlobTypeDescriptor.DEFAULT, InputStreamTypeDescriptor.INSTANCE );
    }

    public String getName() {
        return "inputStream_blob";
    }
}


public class InputStreamTypeDescriptor extends AbstractTypeDescriptor<InputStream> {
    public static final InputStreamTypeDescriptor INSTANCE = new InputStreamTypeDescriptor();

    public static class InputStreamMutabilityPlan implements MutabilityPlan<InputStream> {
        public static final InputStreamMutabilityPlan INSTANCE = new InputStreamMutabilityPlan();

        public boolean isMutable() {
            return false;
        }

        public InputStream deepCopy(InputStream value) {
            return value;
        }

        public Serializable disassemble(InputStream value) {
            throw new UnsupportedOperationException( "InputStream are not cacheable" );
        }

        public InputStream assemble(Serializable cached) {
            throw new UnsupportedOperationException( "Blobs are not cacheable" );
        }
    }

    public InputStreamTypeDescriptor() {
        super( InputStream.class, InputStreamMutabilityPlan.INSTANCE );
    }

    /**
     * {@inheritDoc}
     */
    public String toString(InputStream value) {
        final byte[] bytes;

        bytes = DataHelper.extractBytes(value);

        return PrimitiveByteArrayTypeDescriptor.INSTANCE.toString( bytes );
    }

    /**
     * {@inheritDoc}
     */
    public InputStream fromString(String string) {
        return  new   ByteArrayInputStream(PrimitiveByteArrayTypeDescriptor.INSTANCE.fromString(string));
    }

    @Override
    @SuppressWarnings({ "unchecked" })
    public Comparator<InputStream> getComparator() {
        return IncomparableComparator.INSTANCE;
    }

    @Override
    public int extractHashCode(InputStream value) {
        return System.identityHashCode( value );
    }

    @Override
    public boolean areEqual(InputStream one, InputStream another) {
        return one == another;
    }

    @SuppressWarnings({ "unchecked" })
    public <X> X unwrap(InputStream value, Class<X> type, WrapperOptions options) {
        if ( value == null ) {
            return null;
        }


            if ( BinaryStream.class.isAssignableFrom( type ) ) {
                if ( BlobImplementer.class.isInstance( value ) ) {
                    // if the incoming Blob is a wrapper, just pass along its BinaryStream
                    return (X) ( (BlobImplementer) value ).getUnderlyingStream();
                }
                else {
                    // otherwise we need to build a BinaryStream...
                    return (X) new BinaryStreamImpl( DataHelper.extractBytes( value ) );
                }
            }
            else if ( byte[].class.isAssignableFrom( type )) {
                if ( BlobImplementer.class.isInstance( value ) ) {
                    // if the incoming Blob is a wrapper, just grab the bytes from its BinaryStream
                    return (X) ( (BlobImplementer) value ).getUnderlyingStream().getBytes();
                }
                else {
                    // otherwise extract the bytes from the stream manually
                    return (X) DataHelper.extractBytes( value );
                }
            }
            else if (InputStream.class.isAssignableFrom( type )) {
                return (X) value;
            }


        throw unknownUnwrap( type );
    }

    public <X> InputStream wrap(X value, WrapperOptions options) {
        if ( value == null ) {
            return null;
        }

        // Support multiple return types from
        // org.hibernate.type.descriptor.sql.BlobTypeDescriptor
        if ( Blob.class.isAssignableFrom( value.getClass() ) ) {
            Blob lob = options.getLobCreator().wrap((Blob) value);
            try {
                return lob.getBinaryStream() ;
            } catch (SQLException e) {
                throw new HibernateException( "Unable to access blob stream", e );
            }
        }
        else if ( byte[].class.isAssignableFrom( value.getClass() ) ) {
            return  new ByteArrayInputStream(( byte[] ) value);
        }
        else if ( InputStream.class.isAssignableFrom( value.getClass() ) ) {
            InputStream inputStream = ( InputStream ) value;

            return inputStream;

        }

        throw unknownWrap( value.getClass() );
    }
}


UserType的也应该可以,而且简单,出问题的可能性小。前面可以后就没再试,也记下来
public class BlobUserType implements UserType
{
    @Override
    public int[] sqlTypes()
    {
        return new int[]{Types.BLOB};
    }

    @Override
    public Class returnedClass()
    {
        return InputStream.class;
    }

    @Override
    public boolean equals( Object x, Object y ) throws HibernateException
    {
        boolean result;
        if (x == y)
        {
            result = true;
        }
        else if (x == null || y == null)
        {
            result = false;
        }
        else
        {
            result = x.equals( y );
        }
        return result;
    }

    @Override
    public int hashCode( Object x ) throws HibernateException
    {
        return x.hashCode();
    }

    @Override
    public Object nullSafeGet( ResultSet rs, String[] names, SessionImplementor session, Object owner ) throws HibernateException, SQLException
    {
        return rs.getBlob( names[0] ).getBinaryStream();
    }

    @Override
    public void nullSafeSet( PreparedStatement st, Object value, int index, SessionImplementor session ) throws HibernateException, SQLException
    {
        if( value != null )
        {
            InputStream inputStream = (InputStream)value;
            st.setBlob( index, inputStream );
        }
        else
        {
            st.setNull( index, Types.BLOB );
        }
    }

    @Override
    public Object deepCopy( Object value ) throws HibernateException
    {
        return value;
    }

    @Override
    public boolean isMutable()
    {
        return false;
    }

    @Override
    public Serializable disassemble( Object value ) throws HibernateException
    {
        return null;
    }

    @Override
    public Object assemble( Serializable cached, Object owner ) throws HibernateException
    {
        return null;
    }

    @Override
    public Object replace( Object original, Object target, Object owner ) throws HibernateException
    {
        return original;
    }
}
分享到:
评论

相关推荐

    Hibernate对BLOB CLOB操作

    为了实际读取和写入BLOB和CLOB,你需要从文件系统读取数据,然后将其转换为InputStream或Reader,再使用Hibernate提供的方法。例如,你可以使用FileInputStream读取文件,然后将它转换为BLOB,类似地,使用...

    hibernate保存blob,clob对象

    在Java中,Blob和Clob是JDBC API提供的接口,但在Hibernate中,我们可以通过Session对象的save()或saveOrUpdate()方法来操作这些大数据对象。 首先,我们需要在实体类中定义对应的属性。例如,对于一个包含图片信息...

    jdbc+hibernate存取blob字段

    但是,注意在写入BLOB数据时,依然需要将文件内容转换为`InputStream`,传递给Hibernate的`Blob`实现。 总结来说,无论是使用JDBC还是Hibernate,处理Oracle数据库的BLOB字段都需要了解其特殊性,尤其是BLOB字段的...

    JDBC+Hibernate将Blob数据写入Oracle

    本篇将详细介绍如何利用JDBC和Hibernate框架将Blob数据写入Oracle数据库。 首先,Blob数据类型的优点在于其比Long字段有更好的性能,适合存储大量的二进制数据。然而,Blob字段的写入方式与普通字段有所不同,因为...

    使用JDBC和Hibernate来写入Blob型数据到Oracle中

    在Hibernate中,Blob数据可以被映射到类的属性上,通过Session对象的save()或saveOrUpdate()方法进行保存。 首先,你需要在Hibernate配置文件(hibernate.cfg.xml)中配置Oracle数据库的连接信息。然后,在实体类中...

    struts2.1 + hibernate3.2 + spring 2.5 实现blob数据上传、下载

    - 使用Spring的DAO或Service层接口,通过Hibernate的Session对象将Blob对象插入到数据库对应的表中。这通常涉及到一个带有Blob参数的SQL语句,如`INSERT INTO table (id, blob_column) VALUES (?, ?)`,然后使用`...

    hibernate保存图片

    Blob blob = Hibernate.getLobCreator(session).createBlob(is, -1); User user = new User(); user.setName("John Doe"); user.setPhoto(blob); session.save(user); transaction.commit(); // Retrieve ...

    Blob和Clob使用例子

    在Hibernate,一个流行的Java对象关系映射(ORM)框架中,Blob和Clob也被广泛使用,特别是在处理大型图片、文件或长文本时。 在Hibernate和Microsoft SQL Server的环境中,Blob常用来存储图像、音频、视频等二进制...

    jsp实现文件上传下载

    使用`org.hibernate.type.BinaryType`作为映射类型,并调用`session.save()`或`session.update()`方法保存到数据库。 3. 文件内容读取:在文件下载时,从数据库中查询出BLOB字段,转换为字节数组,然后通过HTTP响应...

    SSH+Oracle上传图片

    在Struts2的Action类`AdminAction`中,定义上传图片的`File upload`和图片ID`Long id`等属性,以及`InputStream is`用于处理图片数据。在`add`方法中,读取上传文件,转换为字节数组,并保存到Admin对象中。在`list...

Global site tag (gtag.js) - Google Analytics