[英]One-to-one and one-to-many association to same domain class in Grails
I have two domain classes -- Account
and Member
, and I am having trouble finding the correct combination of associations and mappedBy
attributes to model their relationship. 我有两个域类
Account
和Member
,并且在查找关联和mappedBy
属性的正确组合以建模它们的关系时遇到了麻烦。 In plain English, an Account
requires one and only one primary member. 用简单的英语来说,一个
Account
只需要一个主要成员。 It also has 0 - many dependents. 它还有0个-许多依赖项。 My initial attempt looked like:
我最初的尝试看起来像:
Account.groovy Account.groovy
class Account {
String displayId
Member primaryMember
SortedSet<Member> dependents = new TreeSet<Member>()
static belongsTo = [Member]
static hasMany = [dependents: Member]
}
Member.groovy Member.groovy
class Member implements Comparable<Member> {
MemberType memberType = MemberType.PRIMARY
String firstName
String lastName
static belongsTo = [account: Account]
@Override
int compareTo(Member m) {
return (this.memberType <=> m?.memberType) * 100 + (this.lastName <=> m?.lastName) * 10 + (this.firstName <=> m?.firstName)
}
}
This causes problems when I attempt to instantiate and persist the accounts and members. 当我尝试实例化并保留帐户和成员时,这会导致问题。 For example,
例如,
AccountIntegrationTests.groovy AccountIntegrationTests.groovy
class AccountIntegrationTests extends GroovyTestCase {
Account smiths
Member john
Member jane
@Before
void setup() {}
@Test
void testShouldLoadAccountWithNoDependents() {
// Arrange
smiths = new Account(displayId: "ABCDEFG")
john = new Member(firstName: "John", lastName: "Smith", memberType: MemberType.PRIMARY)
smiths.primaryMember = john
smiths.save(flush: true, failOnError: true)
def smithsId = smiths.id
smiths.discard()
// Act
def loadedSmiths = Account.get(smithsId)
// Assert
assert loadedSmiths.members.size() == 1
assert loadedSmiths.primaryMember == john
assert loadedSmiths.dependents.size() == 0
}
@Test
void testShouldLoadAccountWithOneDependent() {
// Arrange
smiths = new Account(displayId: "ABCDEFG")
john = new Member(firstName: "John", lastName: "Smith", memberType: MemberType.PRIMARY)
smiths.primaryMember = john
smiths.addToDependents(new Member(firstName: "Jane", lastName: "Smith", memberType: MemberType.DEPENDENT))
smiths.save(flush: true, failOnError: true)
john = smiths.primaryMember
jane = smiths.dependents.first()
def smithsId = smiths.id
smiths.discard()
// Act
def loadedSmiths = Account.get(smithsId)
// Assert
assert loadedSmiths.members.size() == 2
assert loadedSmiths.primaryMember.firstName == "john"
assert loadedSmiths.dependents.size() == 1
assert loadedSmiths.dependents.first().firstName == "jane"
}
}
will throw exceptions because the database tables for the second test look like 将抛出异常,因为第二个测试的数据库表看起来像
Account 帐户
id | display_id
1 | ABCDEFG
Member 会员
id | first_name | last_name | member_type | account_id
1 | John | Smith | Primary | 1
2 | Jane | Smith | Dependent | 1
Obviously I would like the account to retrieve John as the primary member, and Jane as the dependent, but when GORM tries to load account.primaryMember, it throws a Hibernate exception that there are multiple rows (in Member) matching the account ID (1). 显然,我希望该帐户以John为主要成员,而Jane为从属,但是当GORM尝试加载account.primaryMember时,它将引发一个Hibernate异常,即(成员中)有多行与该帐户ID相匹配(1 )。 I need a
mappedBy
discriminator to distinguish between the two associations, but the versions I have tried did not work: 我需要一个
mappedBy
区分mappedBy
来区分两个关联,但是我尝试过的版本不起作用:
Account 帐户
static mappedBy = [primaryMember: 'primaryMember', dependents: 'dependents']
- or -
static mappedBy = [dependents: 'account']
I have read the GORM documentation for both the associations and mappedBy
, as well as various questions on the site regarding multiple associations to the same model , unfortunately they all seem to be modeling multiple hasMany
associations. 我已经阅读了有关关联和
mappedBy
的GORM文档,以及网站上有关同一模型的 多个关联的 各种 问题 ,但不幸的是,它们似乎都在为多个hasMany
关联建模。 The one that does reference both one-to-many and one-to-one relationships to the same model illustrates it as: 确实将一对多关系和一对一关系都引用到同一模型的人将其说明为:
class Person {
String name
static belongsTo = [team: Team]
}
class Team {
String name
static belongsTo = [coach: Person]
static hasMany = [players: Person]
}
However, I tried to use this simple implementation and got: 但是,我尝试使用此简单的实现并得到:
--Output from testShouldLoadAccountWithNoDependents--
| Failure: testShouldLoadAccountWithNoDependents(AccountIntegrationTests)
| org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance - save the transient instance before flushing: Account; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Account
at AccountIntegrationTests.testShouldLoadAccountWithNoDependents(AccountIntegrationTests.groovy:26)
Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Account
... 1 more
AccountIntegrationTests.groovy:26
is the line smiths.save(flush: true, failOnError: true)
. AccountIntegrationTests.groovy:26
是行smiths.save(flush: true, failOnError: true)
。 When I modified the Team/Account
class to: 当我将
Team/Account
类修改为:
class Team {
String name
Person coach
static hasMany = [players: Person]
}
I encountered the same exception, so I believe some kind of cascade
is required. 我遇到了相同的异常,因此我认为需要某种
cascade
。 I tried adding a cascade
to the Account
: 我尝试向该
Account
添加一个cascade
:
Account 帐户
static mapping = {
primaryMember cascade: 'all'
dependents cascade: 'all-delete-orphan'
}
then I also tried using event triggers: 然后我也尝试使用事件触发器:
Account 帐户
def beforeInsert() {
if (primaryMember?.isDirty()) {
primaryMember.save()
}
}
def beforeUpdate() {
if (primaryMember?.isDirty()) {
primaryMember.save()
}
}
Unfortunately, neither of these approaches resolved the transient instance
exception. 不幸的是,这些方法都不能解决
transient instance
异常。 Any assistance on this is greatly appreciated. 在这方面的任何帮助将不胜感激。
The embarrassingly simple solution was to remove the static belongsTo = [account: Account]
from Member
. 令人尴尬的简单解决方案是从
Member
删除static belongsTo = [account: Account]
。 The bidirectional association was causing the issues. 双向关联导致了问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.