Java byte[] 的正确休眠注释
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3677380/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
proper hibernate annotation for byte[]
提问by Justin
I have an application using hibernate 3.1 and JPA annotations. It has a few objects with byte[] attributes (1k - 200k in size). It uses the JPA @Lob annotation, and hibernate 3.1 can read these just fine on all major databases -- it seems to hide the JDBC Blob vendor peculiarities (as it should do).
我有一个使用 hibernate 3.1 和 JPA 注释的应用程序。它有一些具有 byte[] 属性的对象(大小为 1k - 200k)。它使用 JPA @Lob 注释,并且 hibernate 3.1 可以在所有主要数据库上很好地读取这些注释——它似乎隐藏了 JDBC Blob 供应商的特性(它应该这样做)。
@Entity
public class ConfigAttribute {
@Lob
public byte[] getValueBuffer() {
return m_valueBuffer;
}
}
We had to upgrade to 3.5, when we discovered that hibernate 3.5 breaks (and won't fix)this annotation combination in postgresql (with no workaround). I have not found a clear fix so far, but I did notice that if I just remove the @Lob, it uses the postgresql type bytea (which works, but only on postgres).
我们不得不升级到 3.5,当我们发现 hibernate 3.5 中断(并且不会修复)postgresql 中的这个注释组合(没有解决方法)。到目前为止,我还没有找到明确的修复方法,但我确实注意到,如果我只是删除 @Lob,它会使用 postgresql 类型 bytea(它有效,但仅适用于 postgres)。
annotation postgres oracle works on
-------------------------------------------------------------
byte[] + @Lob oid blob oracle
byte[] bytea raw(255) postgresql
byte[] + @Type(PBA) oid blob oracle
byte[] + @Type(BT) bytea blob postgresql
once you use @Type, @Lob seems to not be relevant
note: oracle seems to have deprecated the "raw" type since 8i.
I am looking for a way to have a single annotated class (with a blob property) which is portable across major databases.
我正在寻找一种方法来拥有一个可以跨主要数据库移植的带注释的类(带有 blob 属性)。
- What is the portable way to annotate a byte[] property?
- Is this fixed in some recent version of hibernate?
- 注释 byte[] 属性的可移植方式是什么?
- 这是否已在某些最新版本的休眠中修复?
Update:After reading this blogI have finally figured out what the original workaround in the JIRA issue was: Apparently you are supposed to drop @Lob and annotate the property as:
更新:阅读此博客后,我终于弄清楚了 JIRA 问题中的原始解决方法是:显然您应该删除 @Lob 并将该属性注释为:
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
byte[] getValueBuffer() {...
However, this does not work for me-- I still get OIDs instead of bytea; it did however work for the author of the JIRA issue, who seemed to want oid.
但是,这对我不起作用——我仍然得到 OID 而不是 bytea;然而,它确实适用于 JIRA 问题的作者,他似乎想要 oid。
After the answer from A. Garcia, I then tried this combo, which actually does work on postgresql, but not on oracle.
在 A. Garcia 的回答之后,我尝试了这个组合,它实际上在 postgresql 上有效,但在 oracle 上无效。
@Type(type="org.hibernate.type.BinaryType")
byte[] getValueBuffer() {...
What I really need to do is control which @org.hibernate.annotations.Type the combination (@Lob + byte[] gets mapped) to (on postgresql).
我真正需要做的是控制@org.hibernate.annotations.Type 组合(@Lob + byte[] 被映射)到(在postgresql 上)。
Here is the snippet from 3.5.5.Final from MaterializedBlobType (sql type Blob). According to Steve's blog, postgresql wants you to use Streams for bytea (don't ask me why) and postgresql's custom Blob type for oids. Note also that using setBytes() on JDBC is also for bytea (from past experience). So this explains why use-streams has no affect they both assume 'bytea'.
这是来自 MaterializedBlobType(sql 类型 Blob)的 3.5.5.Final 的片段。根据 Steve 的博客,postgresql 希望您将 Streams 用于 bytea(不要问我为什么)和 postgresql 的自定义 Blob 类型用于 oid。另请注意,在 JDBC 上使用 setBytes() 也适用于 bytea(根据过去的经验)。所以这解释了为什么 use-streams 没有影响他们都假设 '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 );
}
}
This results in:
这导致:
ERROR: column "signature" is of type oid but expression is of type bytea
UpdateThe next logical question is: "why not just change the table definitions manually to bytea" and keep the (@Lob + byte[])? This doeswork, UNTILyou try to store a null byte[]. Which the postgreSQL driver thinks is an OID type expression and the column type is bytea -- this is because hibernate (rightly) calls JDBC.setNull() instead of JDBC.setBytes(null) which PG driver expects.
更新下一个合乎逻辑的问题是:“为什么不手动将表定义更改为 bytea”并保留 (@Lob + byte[])?这确实有效,直到您尝试存储空字节 []。postgreSQL 驱动程序认为这是一个 OID 类型表达式,列类型是 bytea——这是因为 hibernate(正确地)调用 JDBC.setNull() 而不是 PG 驱动程序期望的 JDBC.setBytes(null)。
ERROR: column "signature" is of type bytea but expression is of type oid
The type system in hibernate is currently a 'work in progress' (according to 3.5.5 deprecation comment). In fact so much of the 3.5.5 code is deprecated, it is hard to know what to look at when sub-classing the PostgreSQLDialect).
hibernate 中的类型系统目前是“正在进行的工作”(根据 3.5.5 弃用评论)。事实上,3.5.5 中的大部分代码都被弃用了,很难知道在对 PostgreSQLDialect 进行子类化时该看什么)。
AFAKT, Types.BLOB/'oid' on postgresql should be mapped to some custom type which uses OID style JDBC access (i.e. PostgresqlBlobType object and NOT MaterializedBlobType). I've never actually successfully used Blobs with postgresql, but I do know that bytea just simply works as one / I would expect.
AFAKT,postgresql 上的 Types.BLOB/'oid' 应该映射到一些使用 OID 样式 JDBC 访问的自定义类型(即 PostgresqlBlobType 对象和 NOT MaterializedBlobType)。我从来没有真正成功地将 Blob 与 postgresql 一起使用,但我知道 bytea 只是简单地工作/我所期望的。
I am currently looking at the BatchUpdateException -- its possible that the driver doesn't support batching.
我目前正在查看 BatchUpdateException - 驱动程序可能不支持批处理。
Great quote from 2004: "To sum up my ramblings, I'd say they we should wait for the JDBC driver to do LOBs properly before changing Hibernate."
2004 年的精彩引述:“总结一下我的胡言乱语,我想说他们应该等待 JDBC 驱动程序正确执行 LOB,然后再更改 Hibernate。”
References:
参考:
- https://forum.hibernate.org/viewtopic.php?p=2393203
- https://forum.hibernate.org/viewtopic.php?p=2435174
- http://hibernate.atlassian.net/browse/HHH-4617
- http://postgresql.1045698.n5.nabble.com/Migration-to-Hibernate-3-5-final-td2175339.html
- https://jira.springframework.org/browse/SPR-2318
- https://forums.hibernate.org/viewtopic.php?p=2203382&sid=b526a17d9cf60a80f13d40cf8082aafd
- http://virgo47.wordpress.com/2008/06/13/jpa-postgresql-and-bytea-vs-oid-type/
- https://forum.hibernate.org/viewtopic.php?p=2393203
- https://forum.hibernate.org/viewtopic.php?p=2435174
- http://hibernate.atlassian.net/browse/HHH-4617
- http://postgresql.1045698.n5.nabble.com/Migration-to-Hibernate-3-5-final-td2175339.html
- https://jira.springframework.org/browse/SPR-2318
- https://forums.hibernate.org/viewtopic.php?p=2203382&sid=b526a17d9cf60a80f13d40cf8082aafd
- http://virgo47.wordpress.com/2008/06/13/jpa-postgresql-and-bytea-vs-oid-type/
采纳答案by Pascal Thivent
What is the portable way to annotate a byte[] property?
注释 byte[] 属性的可移植方式是什么?
It depends on what you want. JPA can persist a non annotated byte[]
. From the JPA 2.0 spec:
这取决于你想要什么。JPA 可以保留未注释的byte[]
. 从 JPA 2.0 规范:
11.1.6 Basic Annotation
The
Basic
annotation is the simplest type of mapping to a database column. TheBasic
annotation can be applied to a persistent property or instance variable of any of the following types: Java primitive, types, wrappers of the primitive types,java.lang.String
,java.math.BigInteger
,java.math.BigDecimal
,java.util.Date
,java.util.Calendar
,java.sql.Date
,java.sql.Time
,java.sql.Timestamp
,byte[]
,Byte[]
,char[]
,Character[]
, enums, and any other type that implementsSerializable
. As described in Section 2.8, the use of theBasic
annotation is optional for persistent fields and properties of these types. If the Basic annotation is not specified for such a field or property, the default values of the Basic annotation will apply.
11.1.6 基本注解
的
Basic
注释是映射到数据库列的最简单的类型。所述Basic
注释可以应用于以下任何类型的持久性或实例变量:Java原始,类型,原始类型的包装,java.lang.String
,java.math.BigInteger
,java.math.BigDecimal
,java.util.Date
,java.util.Calendar
,java.sql.Date
,java.sql.Time
,java.sql.Timestamp
,byte[]
,Byte[]
,char[]
,Character[]
,枚举,以及任何其他类型的器具Serializable
. 如第 2.8 节所述,Basic
注释的使用对于这些类型的持久字段和属性是可选的。如果未为此类字段或属性指定 Basic 注释,则将应用 Basic 注释的默认值。
And Hibernate will map a it "by default" to a SQL VARBINARY
(or a SQL LONGVARBINARY
depending on the Column
size?) that PostgreSQL handles with a bytea
.
并且 Hibernate 会将它“默认”映射到 PostgreSQL 处理的 SQL VARBINARY
(或LONGVARBINARY
取决于Column
大小的 SQL ?)bytea
。
But if you want the byte[]
to be stored in a Large Object, you should use a @Lob
. From the spec:
但是,如果您希望byte[]
将 存储在大对象中,则应该使用@Lob
. 从规范:
11.1.24 Lob Annotation
A
Lob
annotation specifies that a persistent property or field should be persisted as a large object to a database-supported large object type. Portable applications should use theLob
annotation when mapping to a databaseLob
type. TheLob
annotation may be used in conjunction with the Basic annotation or with theElementCollection
annotation when the element collection value is of basic type. ALob
may be either a binary or character type. TheLob
type is inferred from the type of the persistent field or property and, except for string and character types, defaults to Blob.
11.1.24 Lob 注释
甲
Lob
注释指定持久性属性或字段应保持为一个大型对象到数据库支持的大对象类型。Lob
当映射到数据库Lob
类型时,便携式应用程序应该使用 注释。当元素集合值为基本类型时,该Lob
注解可以与Basic注解结合使用或与ElementCollection
注解结合使用 。ALob
可以是二进制或字符类型。该Lob
类型是从持久字段或属性的类型推断出来的,除字符串和字符类型外,默认为 Blob。
And Hibernate will map it to a SQL BLOB
that PostgreSQL handles with a oid
.
并且 Hibernate 会将其映射到BLOB
PostgreSQL 处理的 SQL并带有oid
.
Is this fixed in some recent version of hibernate?
这是否已在某些最新版本的休眠中修复?
Well, the problem is that I don't know what the problem is exactly. But I can at least say that nothing has changed since 3.5.0-Beta-2 (which is where a changed has been introduced)in the 3.5.x branch.
好吧,问题是我不知道问题到底是什么。但我至少可以说,自 3.5.0-Beta-2(这是在 3.5.x 分支中引入更改的地方)以来没有任何变化。
But my understanding of issues like HHH-4876, HHH-4617and of PostgreSQL and BLOBs(mentioned in the javadoc of the PostgreSQLDialect
) is that you are supposed to set the following property
但我对HHH-4876、HHH-4617以及PostgreSQL 和 BLOB(在 的 javadoc 中提到 PostgreSQLDialect
)等问题的理解是,您应该设置以下属性
hibernate.jdbc.use_streams_for_binary=false
if you want to use oid
i.e. byte[]
with @Lob
(which is my understanding since VARBINARY
is not what you want with Oracle). Did you try this?
如果你想使用oid
ie byte[]
with @Lob
(这是我的理解,因为VARBINARY
这不是你想要的 Oracle )。你试过这个吗?
As an alternative, HHH-4876suggests using the deprecated PrimitiveByteArrayBlobType
to get the old behavior (pre Hibernate 3.5).
作为替代方案,HHH-4876建议使用已弃用的PrimitiveByteArrayBlobType
来获得旧行为(Hibernate 3.5 之前)。
References
参考
- JPA 2.0 Specification
- Section 2.8 "Mapping Defaults for Non-Relationship Fields or Properties"
- Section 11.1.6 "Basic Annotation"
- Section 11.1.24 "Lob Annotation"
- JPA 2.0 规范
- 第 2.8 节“非关系字段或属性的映射默认值”
- 第 11.1.6 节“基本注释”
- 第 11.1.24 节“Lob 注释”
Resources
资源
回答by Justin
I have finally got this working. It expands on the solution from A. Garcia, however, since the problem lies in the hibernate type MaterializedBlob type just mapping Blob > bytea is not sufficient, we need a replacement for MaterializedBlobType which works with hibernates broken blob support. This implementation only works with bytea, but maybe the guy from the JIRA issue who wanted OID could contribute an OID implementation.
我终于得到了这个工作。它扩展了 A. Garcia 的解决方案,但是,由于问题在于休眠类型 MaterializedBlob 类型,仅映射 Blob > bytea 是不够的,我们需要替换 MaterializedBlobType,它可以与休眠中断的 blob 支持一起使用。此实现仅适用于 bytea,但也许需要 OID 的 JIRA 问题人员可以贡献 OID 实现。
Sadly replacing these types at runtime is a pain, since they should be part of the Dialect. If only this JIRA enhanementgets into 3.6 it would be possible.
遗憾的是,在运行时替换这些类型很痛苦,因为它们应该是方言的一部分。如果只有这个 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";
}
}
Much of this could probably be static (does getBinder() really need a new instance?), but I don't really understand the hibernate internal so this is mostly copy + paste + modify.
其中大部分可能是静态的(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);
}
}
回答by Arthur Ronald
Here goes what O'reilly Enterprise JavaBeans, 3.0 says
这是 O'reilly Enterprise JavaBeans, 3.0 所说的
JDBC has special types for these very large objects. The java.sql.Blob type represents binary data, and java.sql.Clob represents character data.
JDBC 为这些非常大的对象提供了特殊的类型。java.sql.Blob 类型代表二进制数据,java.sql.Clob 代表字符数据。
Here goes PostgreSQLDialect source code
这是 PostgreSQLDialect 源代码
public PostgreSQLDialect() {
super();
...
registerColumnType(Types.VARBINARY, "bytea");
/**
* Notice it maps java.sql.Types.BLOB as oid
*/
registerColumnType(Types.BLOB, "oid");
}
So what you can do
那么你能做什么
Override PostgreSQLDialect as follows
按如下方式覆盖 PostgreSQLDialect
public class CustomPostgreSQLDialect extends PostgreSQLDialect {
public CustomPostgreSQLDialect() {
super();
registerColumnType(Types.BLOB, "bytea");
}
}
Now just define your custom dialect
现在只需定义您的自定义方言
<property name="hibernate.dialect" value="br.com.ar.dialect.CustomPostgreSQLDialect"/>
And use your portable JPA @Lob annotation
并使用您的便携式 JPA @Lob 注释
@Lob
public byte[] getValueBuffer() {
UPDATE
更新
Here has been extracted here
这里已提取here
I have an application running in hibernate 3.3.2 and the applications works fine, with all blob fields using oid (byte[] in java)
我有一个在hibernate 3.3.2 中运行的应用程序并且应用程序工作正常,所有 blob 字段都使用 oid(java 中的 byte[])
...
...
Migrating to hibernate 3.5 all blob fields not work anymore, and the server log shows: ERROR org.hibernate.util.JDBCExceptionReporter - ERROR: column is of type oid but expression is of type bytea
迁移到hibernate 3.5 所有 blob 字段不再起作用,并且服务器日志显示:错误 org.hibernate.util.JDBCExceptionReporter - 错误:列的类型为 oid 但表达式的类型为 bytea
which can be explainedhere
这可以在这里解释
This generaly is not bug in PG JDBC, but change of default implementation of Hibernate in 3.5 version. In my situation setting compatible property on connection did not helped.
这一般不是 PG JDBC 中的错误,而是 3.5 版本中 Hibernate 默认实现的更改。在我的情况下,在连接上设置兼容属性没有帮助。
...
...
Much more this what I saw in 3.5 - beta 2, and i do not know if this was fixed is Hibernate - without @Type annotation - will auto-create column of type oid, but will try to read this as bytea
更多的是我在 3.5 - beta 2 中看到的,我不知道这是否已修复是 Hibernate - 没有 @Type 注释 -将自动创建类型为 oid 的列,但会尝试将其读取为 bytea
Interesting is because when he maps Types.BOLB as bytea (See CustomPostgreSQLDialect) He get
有趣的是,当他将 Types.BOLB 映射为 bytea(参见 CustomPostgreSQLDialect)时,他得到
Could not execute JDBC batch update
无法执行 JDBC 批量更新
when inserting or updating
插入或更新时
回答by Vinh Vo
I got it work by overriding annotation with XML file for Postgres. Annotation is kept for Oracle. In my opinion, in this case it would be best we override the mapping of this trouble-some enity with xml mapping. We can override single / multiple entities with xml mapping. So we would use annotation for our mainly-supported database, and a xml file for each other database.
我通过使用 Postgres 的 XML 文件覆盖注释来实现它。为 Oracle 保留注释。在我看来,在这种情况下,我们最好用 xml 映射覆盖这个麻烦的实体的映射。我们可以使用 xml 映射覆盖单个/多个实体。因此,我们将对我们主要支持的数据库使用注释,并为每个其他数据库使用一个 xml 文件。
Note: we just need to override one single class , so it is not a big deal. Read more from my example Example to override annotation with XML
注意:我们只需要覆盖一个 class ,所以这没什么大不了的。从我的示例示例中阅读更多内容 以使用 XML 覆盖注释
回答by Peter Butkovic
I'm using the Hibernate 4.2.7.SP1 with Postgres 9.3 and following works for me:
我将 Hibernate 4.2.7.SP1 与 Postgres 9.3 一起使用,以下对我有用:
@Entity
public class ConfigAttribute {
@Lob
public byte[] getValueBuffer() {
return m_valueBuffer;
}
}
as Oracle has no trouble with that, and for Postgres I'm using custom dialect:
因为 Oracle 对此没有任何问题,对于 Postgres,我使用的是自定义方言:
public class PostgreSQLDialectCustom extends PostgreSQL82Dialect {
@Override
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
if (sqlTypeDescriptor.getSqlType() == java.sql.Types.BLOB) {
return BinaryTypeDescriptor.INSTANCE;
}
return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
}
}
the advantage of this solution I consider, that I can keep hibernate jars untouched.
我认为这个解决方案的优点是,我可以保持休眠罐不变。
For more Postgres/Oracle compatibility issues with Hibernate, see my blog post.
有关 Hibernate 的更多 Postgres/Oracle 兼容性问题,请参阅我的博客文章。
回答by gajendra kumar
On Postgres @Lob is breaking for byte[] as it tries to save it as oid, and for String also same problem occurs. Below code is breaking on postgres which is working fine on oracle.
在 Postgres 上,@Lob 正在破坏 byte[],因为它试图将其保存为 oid,而对于 String,也会出现同样的问题。下面的代码在 postgres 上被破坏了,它在 oracle 上运行良好。
@Lob
private String stringField;
and
和
@Lob
private byte[] someByteStream;
In order to fix above on postgres have written below custom hibernate.dialect
为了修复上面在 postgres 上写的自定义 hibernate.dialect
public class PostgreSQLDialectCustom extends PostgreSQL82Dialect{
public PostgreSQLDialectCustom()
{
super();
registerColumnType(Types.BLOB, "bytea");
}
@Override
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
if (Types.CLOB == sqlTypeDescriptor.getSqlType()) {
return LongVarcharTypeDescriptor.INSTANCE;
}
return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
}
}
Now configure custom dialect in hibernate
现在在休眠中配置自定义方言
hibernate.dialect=X.Y.Z.PostgreSQLDialectCustom
X.Y.Z is package name.
XYZ 是包名。
Now it working fine. NOTE- My Hibernate version - 5.2.8.Final Postgres version- 9.6.3
现在它工作正常。注意 - 我的 Hibernate 版本 - 5.2.8.Final Postgres 版本 - 9.6.3
回答by El Ghandor Yasser
i fixed My issue by adding the annotation of @Lob which will create the byte[] in oracle as blob , but this annotation will create the field as oid which not work properly , To make byte[] created as bytea i made customer Dialect for postgres as below
我通过添加 @Lob 的注释来解决我的问题,该注释将在 oracle 中创建 byte[] 为 blob,但此注释会将字段创建为 oid 无法正常工作,为了使 byte[] 创建为 bytea,我为客户方言创建了postgres 如下
Public class PostgreSQLDialectCustom extends PostgreSQL82Dialect {
public PostgreSQLDialectCustom() {
System.out.println("Init PostgreSQLDialectCustom");
registerColumnType( Types.BLOB, "bytea" );
}
@Override
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
if (sqlTypeDescriptor.getSqlType() == java.sql.Types.BLOB) {
return BinaryTypeDescriptor.INSTANCE;
}
return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
}
}
Also need to override parameter for the Dialect
还需要覆盖方言的参数
spring.jpa.properties.hibernate.dialect=com.ntg.common.DBCompatibilityHelper.PostgreSQLDialectCustom
spring.jpa.properties.hibernate.dialect=com.ntg.common.DBCompatibilityHelper.PostgreSQLDialectCustom
more hint can be found her : https://dzone.com/articles/postgres-and-oracle
更多提示可以找到她:https: //dzone.com/articles/postgres-and-oracle
回答by Nibin Jacob Panicker
Thanks Justin, Pascal for guiding me to the right direction. I was also facing the same issue with Hibernate 3.5.3. Your research and pointers to the right classes had helped me identify the issue and do a fix.
感谢贾斯汀,帕斯卡引导我走向正确的方向。Hibernate 3.5.3 也遇到了同样的问题。您的研究和对正确课程的指导帮助我确定了问题并进行了修复。
For the benefit for those who are still stuck with Hibernate 3.5 and using oid + byte[] + @LoB combination, following is what I have done to fix the issue.
为了让那些仍然坚持使用 Hibernate 3.5 并使用 oid + byte[] + @LoB 组合的人受益,以下是我为解决该问题所做的工作。
I created a custom BlobType extending MaterializedBlobType and overriding the set and the get methods with the oid style access.
public class CustomBlobType extends MaterializedBlobType { private static final String POSTGRESQL_DIALECT = PostgreSQLDialect.class.getName(); /** * Currently set dialect. */ private String dialect = hibernateConfiguration.getProperty(Environment.DIALECT); /* * (non-Javadoc) * @see org.hibernate.type.AbstractBynaryType#set(java.sql.PreparedStatement, java.lang.Object, int) */ @Override public void set(PreparedStatement st, Object value, int index) throws HibernateException, SQLException { byte[] internalValue = toInternalFormat(value); if (POSTGRESQL_DIALECT.equals(dialect)) { try { //I had access to sessionFactory through a custom sessionFactory wrapper. st.setBlob(index, Hibernate.createBlob(internalValue, sessionFactory.getCurrentSession())); } catch (SystemException e) { throw new HibernateException(e); } } else { st.setBytes(index, internalValue); } } /* * (non-Javadoc) * @see org.hibernate.type.AbstractBynaryType#get(java.sql.ResultSet, java.lang.String) */ @Override public Object get(ResultSet rs, String name) throws HibernateException, SQLException { Blob blob = rs.getBlob(name); if (rs.wasNull()) { return null; } int length = (int) blob.length(); return toExternalFormat(blob.getBytes(1, length)); } }
Register the CustomBlobType with Hibernate. Following is what i did to achieve that.
hibernateConfiguration= new AnnotationConfiguration(); Mappings mappings = hibernateConfiguration.createMappings(); mappings.addTypeDef("materialized_blob", "x.y.z.BlobType", null);
我创建了一个自定义 BlobType,扩展 MaterializedBlobType 并使用 oid 样式访问覆盖 set 和 get 方法。
public class CustomBlobType extends MaterializedBlobType { private static final String POSTGRESQL_DIALECT = PostgreSQLDialect.class.getName(); /** * Currently set dialect. */ private String dialect = hibernateConfiguration.getProperty(Environment.DIALECT); /* * (non-Javadoc) * @see org.hibernate.type.AbstractBynaryType#set(java.sql.PreparedStatement, java.lang.Object, int) */ @Override public void set(PreparedStatement st, Object value, int index) throws HibernateException, SQLException { byte[] internalValue = toInternalFormat(value); if (POSTGRESQL_DIALECT.equals(dialect)) { try { //I had access to sessionFactory through a custom sessionFactory wrapper. st.setBlob(index, Hibernate.createBlob(internalValue, sessionFactory.getCurrentSession())); } catch (SystemException e) { throw new HibernateException(e); } } else { st.setBytes(index, internalValue); } } /* * (non-Javadoc) * @see org.hibernate.type.AbstractBynaryType#get(java.sql.ResultSet, java.lang.String) */ @Override public Object get(ResultSet rs, String name) throws HibernateException, SQLException { Blob blob = rs.getBlob(name); if (rs.wasNull()) { return null; } int length = (int) blob.length(); return toExternalFormat(blob.getBytes(1, length)); } }
向 Hibernate 注册 CustomBlobType。以下是我为实现这一目标所做的工作。
hibernateConfiguration= new AnnotationConfiguration(); Mappings mappings = hibernateConfiguration.createMappings(); mappings.addTypeDef("materialized_blob", "x.y.z.BlobType", null);