apache / apache/grails-core

One To One relationship automatic assignment issue

Open
#14,652 0 comments 0 reactions 0 assignees View on GitHub
relates-to: gorm
Dominant language
Groovy
Stars
2.9k
Forks
975
Avg merge
1d 22h
Merged PRs (30d)
92

Description

One to One relationship without any ownership: Setting one side in constructor results in reverse automatically set. I could reluctantly live with this if it is the officially supported behaviour, but would need to be explicitly documented so not not burn unsuspecting user, or disappear in a future release.

Sample in:

https://github.com/hakanernam/grails-onetoone

```
class Brother {
String name;
Sister favouriteSister

static constraints = {
favouriteSister nullable:true
}
String toString(){
"$id:$name --> ${favouriteSister?.name}"
}
}

class Sister {
String name;
Brother favouriteBrother

static constraints = {
favouriteBrother nullable:true
}
String toString(){
"$id:$name --> ${favouriteBrother?.name}"
}
}
```

and BrotherController action, setting favouriteSister in the constructor:

```
@Transactional
def setFavouriteSister(){
Sister sister = Sister.get(params.id)
log.info("Sister before:" + sister)
def brother = new Brother(favouriteSister: sister);
brother.name = "Harry";

log.info("Brother: " + brother)
log.info("Sister after:" + sister)

brother.save(flush:true, failOnError:true)
forward action:"index"
}

INFO grails.app.controllers.onetoone.BrotherController - Sister before:2:Mary --> null
INFO grails.app.controllers.onetoone.BrotherController - Brother: null:Harry --> Mary
INFO grails.app.controllers.onetoone.BrotherController - Sister after:2:Mary --> Harry
```

results in automatic setting of favouriteBrother of the Sister instance. This is not what I expected, given there is no ownership in the relationship. In my actual use case, this is okay, although made me chase through my code, so not in line with least surprise principle, so I came up with the example, I may be her favourite Brother, but the reverse is not necessarily true.

![brother1](https://cloud.githubusercontent.com/assets/1321157/15479871/1767be34-212b-11e6-9c52-38fbee10cfe4.png)
![sister1](https://cloud.githubusercontent.com/assets/1321157/15479874/21b91f54-212b-11e6-9727-248aaf40ed05.png)

---

In the SisterController, if we set favouriteBrother explicitly, then reverse direction is not set, which I believe the correct result.

```
@Transactional
def setFavouriteBrother(){
Brother bro = Brother.get(params.id)
log.info("Brother before:" + bro)

def sister = new Sister();
sister.name = "Jane"
sister.favouriteBrother = bro;

log.info("Sister: " + sister)
log.info("Brother after:" + bro)

sister.save(flush:true, failOnError:true)
forward action:"index"
}

INFO grails.app.controllers.onetoone.SisterController - Brother before:1:John --> null
INFO grails.app.controllers.onetoone.SisterController - Sister: null:Jane --> John
INFO grails.app.controllers.onetoone.SisterController - Brother after:1:John --> null
```

![sister2](https://cloud.githubusercontent.com/assets/1321157/15479933/6e50df00-212b-11e6-9167-dd42df8f53b0.png)

![brother2](https://cloud.githubusercontent.com/assets/1321157/15479945/7d183628-212b-11e6-8f62-4a2c06bc554a.png)

Contributor guide

Open the contributing guide

Research direction

Start with the linked hakanernam/grails-onetoone sample and compare the BrotherController and SisterController actions shown in the report. Trace the one-to-one relationship assignment and persistence behavior, then establish whether the reverse update is intended; done means the behavior is corrected or explicitly documented with a regression test.

Written by the indexing model from the issue text.

Assessment

Tech stack
groovy
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.