0

私には2つのドメインクラスがあります-AccountMember、そしてそれらの関係をモデル化するための関連付けとmappedBy属性の正しい組み合わせを見つけるのに問題があります。平易な英語では、Accountは1人の主要メンバーのみを必要とします。また、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"
    }
}

2番目のテストのデータベーステーブルは次のように見えるため、例外がスローされます

アカウント

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を読み込もうとすると、アカウントID(1 )。mappedBy2つの関連付けを区別するための識別子が必要ですが、試したバージョンが機能しませんでした。

アカウント

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

アソシエーションとの両方のGORMドキュメント、および同じモデルへの複数のアソシエーションに関するサイト上のさまざまな質問を読みましたがmappedBy残念ながらそれらすべて複数 アソシエーションをモデル化しているようです。同じモデルに対して1対多と1対1の両方の関係を参照しているものは、次のように示しています。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:26smiths.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 に答える