Search code examples
javaormfinalizefinalization

I'm pretty sure finalize is still bad news on later JVMs--is there an alternative?


I would like to implement a ORM-style system that can save updates to POJOs when they are no longer reachable by the caller.

I thought the reference classes could do it, but they seem to only enqueue the reference after the object has been cleared (I was hoping it was when they were able to be collected), so once enqueued the .get() method will always return null.

I could use a finalizer but last time I checked those were questionable (Not guaranteed to run promptly or run at all)--I believe a combination of finalizers and runShutdownHook() would work but that's getting into fairly swampy territory.

Is there another path I'm not thinking besides the obligatory "Just have the caller call .save() when he's done"?


Solution

  • Are you just trying to avoid having to call save() on every POJO that you modify?

    This can be done reliably using a persistence session object, like this:

    1. Open a new session object.
    2. Load objects via the session object. The session object maintains references to all the objects it loads.
    3. Make any changes to the loaded objects. It is not necessary to call a save method on updated objects.
    4. Close the session object. The session saves all of its objects. It might even be fancy enough to keep a copy of clean loaded data, compare all of its objects to the clean data, and save only the ones that have been modified.

    And if you don't want to pass session objects through your code, you can take things a step further with the Unit of Work pattern, associating a session object to the current thread:

    1. Start a unit of work. This creates a session object behind the scenes and associates it with the current thread.
    2. Load objects. Whenever an object is loaded, your ORM automatically associates it with a session object based on the current thread.
    3. Make any changes to the loaded objects. It is not necessary to call a save method on updated objects.
    4. Complete the unit of work. This closes the session object, saving all the objects.

    This fixes several problems with a reachability based solution:

    • You are not relying on nondeterministic garbage collections, which may have a long time between runs, or not run at all.
    • All objects modified in one operation are saved together. If you rely on reachability, different objects modified in the same operation can become unreachable at different times, meaning your modifications can be saved to the database in bits-and-pieces.
    • Rollback is much easier - just give your session object a rollback() method. With a reachability solution, you would need to remember to call rollback() on every modified POJO if an operation fails, which is really the same as your original problem.

    Perhaps see http://nhibernate.info/doc/patternsandpractices/nhibernate-and-the-unit-of-work-pattern.html or research the Unit of Work pattern and emulate some of those ideas.