hibernate 保存blob字段,映射为byte[]正常,映射为Blob或InputStream则报SQL语法错误
跟踪发现PreparedStatement的charEncoding为“GBK”。
检查了表,库和spring配置里都设置了"UTF-8",最后发现是mysql配置文件character_set_server没配置。
是通过以下SQL发现问题,[url=http://blog.csdn.net/tanglongweia2012/article/details/9003022]参考[/url]
mysql> show variables like 'char%';
mysql> show variables like 'collation%';
有段时间没写java了,觉的还是写JS省事。
hibernate4字段映射为InputStream很多自定义UserType都是很久以前的法,找到一个可用的却因为前面的问题没成功,自己仿造了个新的。
UserType的也应该可以,而且简单,出问题的可能性小。前面可以后就没再试,也记下来
@Lob
@Type(type="com.xxx.common.entity.BlobUserType")
private InputStream data;
跟踪发现PreparedStatement的charEncoding为“GBK”。
检查了表,库和spring配置里都设置了"UTF-8",最后发现是mysql配置文件character_set_server没配置。
是通过以下SQL发现问题,[url=http://blog.csdn.net/tanglongweia2012/article/details/9003022]参考[/url]
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;
}
}