Domain Merge does not flush dirty fields to datastore
- Dominant language
- Groovy
- Stars
- 2.9k
- Forks
- 975
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 92
Description
I'm trying to manage updates to a domain object through different controller actions with the object stored in the session. At the end of the editing I'm doing a merge to push the changed fields of the object to the datastore. The merge completes without error but the changes are not sent to the database.
I've reproduced with a simple project -
[grailsMergeBug-bug-report-01112022.zip](https://github.com/grails/gorm-hibernate5/files/9909773/grailsMergeBug-bug-report-01112022.zip). Go to http://localhost:8080/data to reproduce.
The domain object looks like this:
```
package grailsmergebug
import groovy.transform.ToString
@ToString(includePackage = false, includes = ['name', 'number'], includeNames = true)
class Data {
String name
Integer number
static constraints = {}
}
```
Changes to the `name` or `number` fields do not get merge saved.
I've simulated the editing, storing in session and merge in a controller:
```
...
@Transactional
def index() {
Data.deleteAll([flush: true], Data.list())
Data data = new Data(name: "data1", number: 1)
data.save()
redirect(action: 'putInSession')
}
def putInSession() {
Data data = Data.list().first()
data.name = "dirtied"
data.number += 1
logDirtyStatus(data, "putInSession")
session.data = data
redirect(action: 'tryMerge')
}
@Transactional
def tryMerge() {
Data data = session.data
logDirtyStatus(data, "tryMerge")
log.debug "doing merge..."
def mergeRet = data.merge(failOnError: true, flush: true)
log.debug "merge return data: $data"
session.data = null
redirect(action: 'checkSaved')
}
def checkSaved() {
Data data = Data.list().first()
log.debug "checkSaved data: $data"
render "$data -- ${data.name == 'dirtied' ? 'changed OK' : 'did not merge the changes'}"
}
private def logDirtyStatus(Data data, String prefix)
{
log.debug "[$prefix] val: $data.name | hasChanged: ${data.hasChanged()} | hasChanged(field): ${data.hasChanged("name")} | " +
"list dirty: ${data.listDirtyPropertyNames()} | get dirty: ${data.getDirtyPropertyNames()} | " +
"dirty: ${data.dirty} | dirty(field): ${data.isDirty("name")}"
}
...
```
Going to checkSaved action in a browser shows that the object has not been updated.
Versions:
```
grailsVersion=5.2.3
grailsGradlePluginVersion=5.2.3
groovyVersion=3.0.11
gorm.version=7.3.2
```
Contributor guide
Research direction
Start with the attached grailsMergeBug-bug-report-01112022.zip and reproduce the behavior by visiting /data. Read the controller actions putInSession, tryMerge, and checkSaved, then trace the merge call and its flush behavior. Done means changes to name and number made before session storage are persisted and checkSaved reports the updated object.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- groovy
- Domain
- backend, database
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100