我有两个域类 - Account
和 Member
,我无法找到正确的关联组合和 mappedBy
属性来建模它们的关系 . 简单来说, Account
需要一个且只有一个主要成员 . 它也有0个很多家属 . 我最初的尝试看起来像:
Account.groovy
class Account {
String displayId
Member primaryMember
SortedSet<Member> dependents = new TreeSet<Member>()
static belongsTo = [Member]
static hasMany = [dependents: Member]
}
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)
}
}
当我尝试实例化并持久保存帐户和成员时,这会导致问题 . 例如,
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"
}
}
将抛出异常,因为第二个测试的数据库表看起来像
帐户
id | display_id
1 | ABCDEFG
会员
id | first_name | last_name | member_type | account_id
1 | John | Smith | Primary | 1
2 | Jane | Smith | Dependent | 1
显然我希望该帐户检索John作为主要成员,Jane作为依赖,但当GORM尝试加载account.primaryMember时,它会抛出一个Hibernate异常,即有多个行(在Member中)与帐户ID匹配(1 ) . 我需要一个 mappedBy
鉴别器来区分这两个关联,但我尝试过的版本不起作用:
帐户
static mappedBy = [primaryMember: 'primaryMember', dependents: 'dependents']
- or -
static mappedBy = [dependents: 'account']
我已经阅读了关联和mappedBy的GORM文档,以及the site上的various questions关于multiple associations到same model,不幸的是它们似乎都在建模多个 hasMany
关联 . 确实引用同一模型的一对多和一对一关系的那个将其表示为:
class Person {
String name
static belongsTo = [team: Team]
}
class Team {
String name
static belongsTo = [coach: Person]
static hasMany = [players: Person]
}
但是,我尝试使用这个简单的实现并得到:
--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
是 smiths.save(flush: true, failOnError: true)
行 . 当我将 Team/Account
类修改为:
class Team {
String name
Person coach
static hasMany = [players: Person]
}
我遇到了同样的异常,所以我相信某种 cascade
是必需的 . 我尝试将 cascade
添加到 Account
:
帐户
static mapping = {
primaryMember cascade: 'all'
dependents cascade: 'all-delete-orphan'
}
然后我也尝试使用事件触发器:
帐户
def beforeInsert() {
if (primaryMember?.isDirty()) {
primaryMember.save()
}
}
def beforeUpdate() {
if (primaryMember?.isDirty()) {
primaryMember.save()
}
}
不幸的是,这些方法都没有解决 transient instance
异常 . 非常感谢对此提供的任何帮助 .
1 回答
令人尴尬的简单解决方案是从
Member
中删除static belongsTo = [account: Account]
. 双向关联导致了这些问题 .