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;
}
}
分享到:
相关推荐
为了实际读取和写入BLOB和CLOB,你需要从文件系统读取数据,然后将其转换为InputStream或Reader,再使用Hibernate提供的方法。例如,你可以使用FileInputStream读取文件,然后将它转换为BLOB,类似地,使用...
在Java中,Blob和Clob是JDBC API提供的接口,但在Hibernate中,我们可以通过Session对象的save()或saveOrUpdate()方法来操作这些大数据对象。 首先,我们需要在实体类中定义对应的属性。例如,对于一个包含图片信息...
但是,注意在写入BLOB数据时,依然需要将文件内容转换为`InputStream`,传递给Hibernate的`Blob`实现。 总结来说,无论是使用JDBC还是Hibernate,处理Oracle数据库的BLOB字段都需要了解其特殊性,尤其是BLOB字段的...
本篇将详细介绍如何利用JDBC和Hibernate框架将Blob数据写入Oracle数据库。 首先,Blob数据类型的优点在于其比Long字段有更好的性能,适合存储大量的二进制数据。然而,Blob字段的写入方式与普通字段有所不同,因为...
在Hibernate中,Blob数据可以被映射到类的属性上,通过Session对象的save()或saveOrUpdate()方法进行保存。 首先,你需要在Hibernate配置文件(hibernate.cfg.xml)中配置Oracle数据库的连接信息。然后,在实体类中...
- 使用Spring的DAO或Service层接口,通过Hibernate的Session对象将Blob对象插入到数据库对应的表中。这通常涉及到一个带有Blob参数的SQL语句,如`INSERT INTO table (id, blob_column) VALUES (?, ?)`,然后使用`...
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 ...
在Hibernate,一个流行的Java对象关系映射(ORM)框架中,Blob和Clob也被广泛使用,特别是在处理大型图片、文件或长文本时。 在Hibernate和Microsoft SQL Server的环境中,Blob常用来存储图像、音频、视频等二进制...
使用`org.hibernate.type.BinaryType`作为映射类型,并调用`session.save()`或`session.update()`方法保存到数据库。 3. 文件内容读取:在文件下载时,从数据库中查询出BLOB字段,转换为字节数组,然后通过HTTP响应...
在Struts2的Action类`AdminAction`中,定义上传图片的`File upload`和图片ID`Long id`等属性,以及`InputStream is`用于处理图片数据。在`add`方法中,读取上传文件,转换为字节数组,并保存到Admin对象中。在`list...