About Peter Butkovic

Peter is a java developer living in the Munich area. Prototyping is for him the most favourite part of the project work (especially in the phase when nobody really knows if things are really gonna work :) He is also quite influenced by the ideas of open source software. And important things except that? Family, friends and Jesus Christ (the best Friend :)

Postgres and Oracle compatibility with Hibernate

There are situations your JEE application needs to support Postgres and Oracle as a Database.
Hibernate should do the job here, however there are some specifics worth mentioning.
While enabling Postgres for application already running Oracle I came across following tricky parts:

  • BLOBs support,
  • CLOBs support,
  • Oracle not knowing Boolean type (using Integer) instead and
  • DUAL table.

These were the tricks I had to apply to make the @Entity classes running on both of these.

Please note I’ve used Postgres 9.3 with Hibernate 4.2.1.SP1.

BLOBs support

The problem with Postgres is that it offers 2 types of BLOB storage:

  • bytea – data stored in table
  • oid – table holds just identifier to data stored elsewhere

I guess in the most of the situations you can live with the bytea as well as I did. The other one as far as I’ve read is to be used for some huge data (in gigabytes) as it supports streams for IO operations.

Well, it sounds nice there is such a support, however using Hibernate in this case can make things quite problematic (due to need to use the specific annotations), especially if you try to achieve compatibility with Oracle.

To see the trouble here, see StackOverflow: proper hibernate annotation for byte[]

All- the combinations are described there:

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

where @Type(PBA) stands for @Type(type="org.hibernate.type.PrimitiveByteArrayBlobType") and @Type(BT) stands for: @Type(type="org.hibernate.type.BinaryType").

These result in all sorts of Postgres errors, like:

ERROR: column “foo” is of type oid but expression is of type bytea

or

ERROR: column “foo” is of type bytea but expression is of type oid

Well, there seems to be a solution, still it includes patching of Hibernate library (something I see as the last option when playing with 3.rd party library).

There is also a reference to official blog post from the Hibernate guys on the topic: PostgreSQL and BLOBs. Still solution described in blog post seems not working for me and based on the comments, seems to be invalid for more people.

BLOBs solved

OK, so now the optimistic part.

After quite some debugging I ended up with the Entity definition like this :

@Lob
private byte[] foo;

Oracle has no trouble with that, moreover I had to customize the Postgres dialect in a way:

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);
  }
}

That’s it! Quite simple right? That works for persisting to bytea typed columns in Postgres (as that fits my usecase).

CLOBs support

The errors in misconfiguration looked something like this:

org.postgresql.util.PSQLException: Bad value for type long : ...

So first I’ve found (on String LOBs on PostgreSQL with Hibernate 3.6) following solution:

@Lob
@Type(type = "org.hibernate.type.TextType")
private String foo;

Well, that works, but for Postgres only.

Then there was a suggestion (on StackOverflow: Postgres UTF-8 clobs with JDBC) from to go for:

@Lob
@Type(type="org.hibernate.type.StringClobType")
private String foo;

That pointed me the right direction (the funny part was that it was just a comment to some answers). It was quite close, but didn’t work for me in all cases, still resulted in errors in my tests.

CLOBs solved

The important was @deprecation javadocs in the org.hibernate.type.StringClobType that brought me to working one:

@Lob
@Type(type="org.hibernate.type.MaterializedClobType")
private String foo;

That works for both Postgres and Oracle, without any further hacking (on Hibernate side) needed.

Boolean type

Oracle knows no Boolean type and the trouble is that Postgres does. As there was also some plain SQL present, I ended up In Postgres with error:

ERROR: column “foo” is of type boolean but expression is of type integer

I decided to enable cast from Integer to Boolean in Postgres rather than fixing all the plain SQL places (in a way found in Forum: Automatically Casting From Integer to Boolean):

update pg_cast set castcontext = 'i' where oid in ( select c.oid from pg_cast c inner join pg_type src on src.oid = c.castsource inner join pg_type tgt on tgt.oid = c.casttarget where src.typname like 'int%' and tgt.typname like 'bool%');

Please note you should run the SQL update by user with provileges to update catalogs (probably not your postgres user used for DB connection from your application), as I’ve learned on Stackoverflow: Postgres – permission denied on updating pg_catalog.pg_cast.

DUAL table

There is one more specific in the Oracle I came across. If you have plain SQL, in Oracle there is DUAL table provied (see more info on Wikipedia on that) that might harm you in Postgres.

Still the solution is simple. In Postgres create a view that would fill the similar purpose. It can be created like this:

create or replace view dual as select 1;

Conclusion

Well that should be it. Enjoy your cross DB compatible JEE apps.
 

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

Leave a Reply


5 + two =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close