为了账号安全,请及时绑定邮箱和手机立即绑定

为byte []设置适当的休眠注释

为byte []设置适当的休眠注释

qq_花开花谢_0 2019-10-16 12:51:30
我有一个使用hibernate 3.1和JPA批注的应用程序。它有一些带有byte []属性的对象(大小为1k-200k)。它使用JPA @Lob批注,并且hibernate 3.1可以在所有主要数据库上读取它们,这似乎隐藏了JDBC Blob供应商的特性(应该这样做)。@Entitypublic class ConfigAttribute {  @Lob  public byte[] getValueBuffer() {    return m_valueBuffer;  }}当我们发现休眠3.5 破坏了(并且不会修复) postgresql中的这个注释组合时(没有解决方法),我们不得不升级到3.5 。到目前为止,我还没有找到明确的修复程序,但是我确实注意到,如果我只是删除@Lob,它将使用postteasql类型bytea(该方法有效,但仅适用于postgres)。annotation                   postgres     oracle      works on-------------------------------------------------------------byte[] + @Lob                oid          blob        oraclebyte[]                       bytea        raw(255)    postgresqlbyte[] + @Type(PBA)          oid          blob        oraclebyte[] + @Type(BT)           bytea        blob        postgresqlonce you use @Type, @Lob seems to not be relevantnote: oracle seems to have deprecated the "raw" type since 8i.我正在寻找一种具有单个注释类(具有blob属性)的方法,该方法可跨主要数据库移植。注释byte []属性的可移植方式是什么?在某些最新的休眠版本中已解决此问题吗?更新: 阅读此博客后,我终于弄清楚JIRA问题中的原始解决方法是:显然,您应该删除@Lob并将其注释为:@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType") byte[] getValueBuffer() {...但是,这对我不起作用-我仍然会获得OID而不是bytea。但是,它确实为JIRA问题的作者带来了帮助,他似乎想要oid。在A. Garcia的回答之后,我然后尝试了这个组合,它实际上在postgresql上有效,但在oracle上不起作用。@Type(type="org.hibernate.type.BinaryType") byte[] getValueBuffer() {...我真正需要做的是控制@ org.hibernate.annotations.type组合(@Lob + byte []被映射)到(在postgresql上)。这是MaterializedBlobType(SQL类型Blob)的3.5.5.Final版本的代码段。根据Steve的博客,postgresql希望您将流用于bytea(不要问我为什么),并将postgresql的自定义Blob类型用于oid。还请注意,在JDBC上使用setBytes()也可用于bytea(根据过去的经验)。因此,这解释了为什么使用流对它们都假定为“ bytea”没有影响。public void set(PreparedStatement st, Object value, int index) { byte[] internalValue = toInternalFormat( value ); if ( Environment.useStreamsForBinary() ) {  // use streams = true   st.setBinaryStream( index,     new ByteArrayInputStream( internalValue ), internalValue.length ); } else {  // use streams = false  st.setBytes( index, internalValue ); }}
查看完整描述

3 回答

?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

我终于完成了这项工作。它扩展了A. Garcia的解决方案,但是,由于问题出在休眠类型MaterializedBlob类型上,仅映射Blob> bytea是不够的,因此我们需要替换MaterializedBlobType,它可以与休眠破碎的Blob支持一起使用。该实现仅适用于bytea,但是JIRA问题中希望OID的人可以为OID实现提供帮助。


可悲的是,在运行时替换这些类型很麻烦,因为它们应该是方言的一部分。如果只有JIRA增强功能进入3.6,那将是可能的。


public class PostgresqlMateralizedBlobType extends AbstractSingleColumnStandardBasicType<byte[]> {

 public static final PostgresqlMateralizedBlobType INSTANCE = new PostgresqlMateralizedBlobType();


 public PostgresqlMateralizedBlobType() {

  super( PostgresqlBlobTypeDescriptor.INSTANCE, PrimitiveByteArrayTypeDescriptor.INSTANCE );

 }


  public String getName() {

   return "materialized_blob";

  }

}

其中的大部分可能是静态的(getBinder()确实需要一个新实例吗?),但是我不太了解休眠内部,因此这主要是复制+粘贴+修改。


public class PostgresqlBlobTypeDescriptor extends BlobTypeDescriptor implements SqlTypeDescriptor {

  public static final BlobTypeDescriptor INSTANCE = new PostgresqlBlobTypeDescriptor();


  public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {

   return new PostgresqlBlobBinder<X>(javaTypeDescriptor, this);

  }

  public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {

   return new BasicExtractor<X>( javaTypeDescriptor, this ) {

    protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException { 

      return (X)rs.getBytes(name);

    }

   };

  }

}


public class PostgresqlBlobBinder<J> implements ValueBinder<J> {

 private final JavaTypeDescriptor<J> javaDescriptor;

 private final SqlTypeDescriptor sqlDescriptor;


 public PostgresqlBlobBinder(JavaTypeDescriptor<J> javaDescriptor, SqlTypeDescriptor sqlDescriptor) { 

  this.javaDescriptor = javaDescriptor; this.sqlDescriptor = sqlDescriptor;

 }  

 ...

 public final void bind(PreparedStatement st, J value, int index, WrapperOptions options) 

 throws SQLException {

  st.setBytes(index, (byte[])value);

 }

}


查看完整回答
反对 回复 2019-10-16
  • 3 回答
  • 0 关注
  • 479 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信