0

我有两个域类 -AccountMember,并且我无法找到关联和mappedBy属性的正确组合来建模它们的关系。用简单的英语来说,anAccount需要一个且只有一个主要成员。它也有 0 - 许多家属。我最初的尝试看起来像:

Account.groovy

class Account {
    String displayId

    Member primaryMember
    SortedSet<Member> dependents = new TreeSet<Member>()

    static belongsTo = [Member]
    static hasMany = [dependents: 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 异常,即有多个行(在成员中)匹配帐户 ID(1 )。我需要一个mappedBy鉴别器来区分这两个关联,但是我尝试过的版本不起作用:

帐户

static mappedBy = [primaryMember: 'primaryMember', dependents: 'dependents']
- or -
static mappedBy = [dependents: 'account']

我已经阅读了关联的 GORM 文档mappedBy,以及网站上关于同一模型多个关联各种 问题,不幸的是,它们似乎都在为多个关联建模。确实将一对多和一对一关系都引用到同一模型的那个将其说明为: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异常。非常感谢您对此的任何帮助。

4

1 回答 1

1

令人尴尬的简单解决方案是删除static belongsTo = [account: Account]from Member。双向关联导致了这些问题。

于 2012-12-07T23:45:03.507 回答