Hibernate version: 2.1.4
Name and version of the database you are using: Oracle 9i (9.2.2)
I've used Hibernate succesfully to deal with LOBs (BLOBs and CLOBs) using a DB2 database. Now I'm trying to use the same code with an Oracle 9i database. The only problem with the migration has been LOBs. Everything else has gone very smoothly, which is a great testimonial to Hibernate. So here's what's going on with the LOBs.
For dealing with LOBs on DB2, I had used the design patterns mentioned in the documentation (
http://www.hibernate.org/73.html -- Blob to byte[] and
http://www.hibernate.org/76.html == Clob to String.) These both worked on Oracle as well, but only for objects of size < 4K. As soon as I went over the 4K limit, I immediately got an error about stream types not being allowed for batch updates. So of course I searched the FAQs and message boards and found this:
http://forum.hibernate.org/viewtopic.ph ... racle+blob.
Now I immediately had a few issues with this solution of turning off batch updates. First, doesn't this obviously cause a performance hit, potentially a pretty significant one? Personally I use a cascading with Hibernate, because I think it makes application code for dealing with highly nested structures much simpler. It's one of my favorite things about Hibernate. So in particular it seems pretty horrible to turn off batching. Maybe my use isn't typical, or maybe the performance hit isn't as bad as it would seem.
At any rate, I guessed that the root of the problem is that Oracle does not allow LOBs to be set in insert statements (or maybe it's not multiple LOBs?) So a seperate insert/update is issued and Hibernate batches them together. If Oracle is not going to allow the batching, shouldn't the Dialect/Configuration/SessionFactory know this and not try to do it? Is there something more going on here that I'm not aware of?
Anyways, I turned off batching and immediately got an error about "connection reset by peer" i.e. my connection closed during the middle of the transaction. I correctly guessed that this was a crash on Oracle, and found the corresponding dump file. Then I (finally) read this:
http://www.hibernate.org/56.html. The pattern itself is very useful, but of course it's not really usable as it creates a memory leak. The many responses provide some great information. They indicate that not only must one write a very Oracle specific UserType, but must also write an Oracle specific Interceptor to take care of the memory leak.
So is this really the only way to handle LOBs with Oracle? After reading all this, my conclusion would be that Oracle LOBs should not be used with Hibernate, as most Hibernate advantages are lost. At the very least a hybrid approach is needed where only the non-LOB fields are mapped using Hibernate and JDBC is used for the LOB fields. It would seem that would involve the same or maybe even less Oracle specific code, and at least it would all be in the same place making it less buggy. Maybe I'm being too harsh, or maybe there is an easier way? Again, should this be stuff handled by the Dialect? Isn't that (one of) the point of a Dialect, that it handle vendor specific special needs?