Hibernate, Postgresql: Column "x" is of type oid but expression is of type byte

Hons picture Hons · Dec 20, 2010 · Viewed 15.8k times · Source

I have a strange problem regarding the hibernate mapping containing large objects (BLOB), when switching between different databases.

@Lob
private byte[] binaryData;

The field above creates a byte array field in MySQL and in Oracle, however in PostreSQL it creates a field of type oid.

Now when I try to access this field it works fine in the other databases, but in PostgreSQL it fails with the following error

Column "binaryData" is of type oid but expression is of type bytea.

So I tried to simply remove the "@Lob" annotation, which will solve the problem for PostgreSQL, however in MySQL without this annotation, hibernate creates a field of type "tinyblob", which is to small in most of our cases. And, as we want to use this project in more than one environment it is annoying to have two different mappings to switch.

Is there any annotation that forces postgreSQL to use bytea instead of oid for fields annotated with @Lob? Or is it somehow possible to omit the @Lob and put something else in order to force MySQL to allocate it with a larger datatype as it would using @Lob?

I could even imagine to have a solution like this

if (field is of type oid)
  store it as oid
else if (field is of type bytea)
  store it as bytea
else
  // not storable

and the same as a getter, if there exists a way to do kind of this

EDIT:

The following declaration is working. It allocates the column as oid, however hibernate using this knows how to store and retrieve data from such a field

@Lob
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
private byte[] binaryFile;

Answer

Don Roby picture Don Roby · Dec 20, 2010

This field mapping is defined in org.hibernate.dialect.PostgreSQLDialect and can be changed by subclassing this and configuring your app to use the modified dialect when running with postgres.

The relevant incantation in the subclass is probably to put

    registerColumnType( Types.BLOB, "bytea" );

in your constructor after a call to super().