Skip to content

Instantly share code, notes, and snippets.

@YaroSpace
Forked from marcpalmer/gist:4058815
Last active August 29, 2015 14:24
Show Gist options
  • Save YaroSpace/711a6cc1b5c5c3b21c5c to your computer and use it in GitHub Desktop.
Save YaroSpace/711a6cc1b5c5c3b21c5c to your computer and use it in GitHub Desktop.
private copyDirtyProperties(src, target) {
for (name in src.dirtyPropertyNames) {
target[name] = src[name]
}
}
private copyDirtyPropertiesNotChangedInTarget(src, target) {
for (name in src.dirtyPropertyNames) {
if (target[name] == src.getPersistentValue(name)) {
target[name] = src[name]
}
}
}
private copyPersistentProperties(src, target) {
def artefact = grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, src.getClass().name)
for (prop in artefact.persistentProperties) {
target[prop.name] = src[prop.name]
}
}
// Now somewhere i.e. in BootStrap...
grailsApplication.domainClasses.clazz.each { domainClass ->
def domainMetaClass = domainClass.metaClass
domainMetaClass.lockUpdateAndRefresh = { Closure updateCode ->
def lockedSelf = delegate.getClass().lock(delegate.ident())
updateCode(lockedSelf)
delegate.refresh()
}
// Obtain lock. If stale, re-load locked and
// merge our existing *dirty* properties according to
// merge policies:
// Changes we've made will overwrite anything new from the DB
domainMetaClass.lockAndMergeSessionIn = { ->
def lockedSelf = delegate.getClass().lock(delegate.ident())
copyDirtyProperties(delegate, lockedSelf)
delegate.refresh()
}
// Changes to the DB will survive, anything we also changed
// will be lost
domainMetaClass.lockAndMergeDatabaseIn = { ->
def lockedSelf = delegate.getClass().lock(delegate.ident())
copyDirtyPropertiesNotChangedInTarget(delegate, lockedSelf)
delegate.refresh()
}
// Exactly the values we have for all properties will be used
// all values from the DB will be lost even if changed and
// they weren't change in this session (coherent)
domainMetaClass.lockAndOverwrite = { ->
def lockedSelf = delegate.getClass().lock(delegate.ident())
copyPersistentProperties(delegate, lockedSelf)
delegate.refresh()
}
// Attempt a lock but if DB changed since object was loaded,
// catch the exception and execute the Closure
domainMetaClass.lockAndIfStale = { Closure staleHandler ->
try {
delegate.lock()
} catch (Exception e) { // Need specific types here, there's a couple
staleHandler(delegate)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment