Monthly Archives: April 2011

Managing Hibernate logical deletes

Recently we discovered a need to apply a “logical delete” on our business entities to avoid screwing up history details and to leave the audit trail intact. “Logical delete” means “mark deleted” instead of issuing physical sql DELETE update.

To implement logical delete on hibernate (3.3.2) you’ll basically need the following ingredients:

  • add @SQLDelete for your entity to update an existing column (property)
  • (optional) setup a filter to filter out all your logically deleted by default, rig @Filter to your entity

After this your Session#delete(Object) will only update the field and if you added the @Filter and apply it your searches (note, not primaryKey loads or gets) will not return the logically deleted.

If by now you have extensive unit tests, which test the behavior on your entity’s relations, you might have noticed that Collections owned by your entity are all deleted. This is because Hibernate does not know whether your @SQLDelete updated or deleted the row, and assumes that it was deleted.

To fix that, you need to roll your own CollectionPersister, most likely by extending
org.hibernate.persister.collection.BasicCollectionPersister. The important method here is #remove(Serializable, SessionImplementor) and it will be called:

  • when the owner entity has been deleted and org.hibernate.event.def.DefaultFlushEntityEventListener notices this
  • when the collection has become empty while it wasn’t previously

Latter point means that just overriding the #remove(..) with empty method will not allow the collections using this persisted be cleared after they have been persisted with at least one entity.

To fix this you need to call super.remove(..) when the owner’s org.hibernate.engine.EntityEntry#getStatus() != org.hibernate.engine.Status.DELETED.

You can find the owner through SessionImplementor#getPersistenceContext()‘s #getCollectionOwner(id, this) and get it’s EntityEntry through PersistenceContext#getEntry(Object).

Add the @Persister(impl=YourCollectionPersister.class) for each of your collections you’d like prevent from being deleted and that’s done.

If you’d like to see built-in logical delete support in hibernate go and share your opinions at HHH-6072.

Advertisements

Spring presentation notes

Usually you should be sleeping at this hour but I just couldn’t, so I stumbled upon a Spring Security 3 presentation from SpringOne 2010 by Mike Wiesner. (Great presentation by the way.)

Quick notes:

  • still a lot of focus on url-based control (surprise) — still cannot see how we could benefit from expressions in our app
  • UserContextService (why didn’t I think of that!! — 00:24:00) — should store only simple serializable token (like username) in Authentication and have UserContextService provide us with the User entity, perhaps the related entities, sids, stuff like that
  • more specific about roles and rights than with 2.0, which is very good — must’ve confused many
    • rights = business actions
  • @PreAuthorize for rules, not acl 00:54:00, with expressions … abstracting “what the permission is” behind “do this permission check” helps with deployment-time/customer customizations; acl is just one way to implement the check
    • DefaultMethodSecurityExpressionHandler
    • PermissionEvaluator 00:59:00
  • looks better and better with PermissionEvaluator
  • yet I’m guessing there’s nothing on database searches with permissions….
    • yep, @PostFilter, lets see if anyone asks the question what to do with 50000 entities
    • Mike Wiesner has good jokes
    • extends PermissionEvaluator to express itself in sql?
  • using groovy for evaluators, less code, more visibility, powerassert 01:08:00 (extermly nice assert error)
  • deleteable discussion 01:11:00 — good stuff; do not push security properties into entities
    • throw in a mix-in … with groovy…
    • basically groovy supports pushing some kind of map store as “mixins”
    • can access from (jsp) expressions — surprise
    • aha, introduce a SecureEntity interface, push it with @Transient using @AspectJ mixin — looks nice, requires compile/load time weaving
    • if we use hibernate session#load, loadable model wrapper to push values might be the best place, or rewrite loaded proxy to use service layer, push behaviour with annotation to service
    • remember to do service first, ui last
  • kerberos/spnego at 1:21:00
    • default on windows, thank god for no more ntlm
    • at the time of presentation at milestone2
    • missing mostly documentation, hardest part should be kerberos environment setup
  • spring security 3.1 at 01:24:00
    • want to have better/easier right mapping (?)
    • better Active Directory integration

And I also used my night on another great presentation by David Syer and Mark Fisher: Concurrent Distributed Applications with Spring.

Notes:

  • first SEDA explanation I’ve understood, with the same old Cafe example
  • way too much JCIP repeating