It's me again with my transmitters and sensors, lucky y'all - back from dealing with SSL (much easier!).
In general Hibernate seems to be working, but... not 100% yet. I have some problems with transactions now, it looks like.
A bit of backdrop as to the code - as this is a Swing app the Hibernate updates are going on in a thread of their own so they don't lag the GUI. Hibernate tasks (save_or_update and delete) are queued onto a ConcurrentLinkedQueue and that thread runs in a loop, sucking tasks off that queue and processing them as quickly as possible.
The transaction code that seems to be iffy is this :-
After this chunk of code a Session.saveOrUpdate() method is called on 'loc', within the scope of a single Transaction.
Payload is a Transmitter object with the following mapping :-
Sometimes there is already a TransmitterLocation associated with payload, sometimes not. Normally this works fine, I can see it the thread chuntering away in the background, there are no errors, everything persists, it all looks good. However, if I spam a whole bunch of operations, sometimes (not reliably but often) an exception is thrown at Transaction.commit().
org.hibernate.AssertionFailure: null id in com.preciselyso.planview.datamodel.TransmitterLocation entry (don't flush the Session after an exception occurs)
Now... you have to bear in mind that the actual update being run by Hibernate is happening 15-20 seconds down the line because its so amazingly slow. As the object being queued up is still live in the application, I presume that these errors happen because by the time Hibernate has worked through the queue to update the object, its state may have changed to the point that the update isn't valid anymore. If I order a TransmitterLocation to be saved, but in the 15 seconds that elapses between that and it actually being persisted I change my mind and delete it, I think that gives me the above error.
So this threading model apparently is a poor choice! My first thought was to populate the queue with cloned objects rather than the live ones, but deep cloning this stuff would be a nightmare due to all the cross linking. I'm curious what strategies others have used to deal with this issue? I also wonder if a shallow clone would be enough - the SQL which failed before the above exception is...
ie its all on TX_PLANPLACE so all within a single object, so a shallow clone might do, no? Problem is these exceptions are unpredictable runtime exceptions caused by me flogging the queue, so 'I tested it and it worked fine for me' is not the same as 'this is the way to do it'. Hence the need for advice.
Note to self: don't get into a fist fight with a cactus. Command this tiny ad to do it: