Relationships between Grails domain classes with inheritance

假装没事ソ 提交于 2019-12-11 11:19:46

问题


I have the following class. In src/groovy,

class Profile {
    String firstName
    String middleName
    String lastName
    byte[] photo
    String bio
}

The domain classes BasicProfile and AcademicProfile extend Profile.

class BasicProfile extends Profile {

    User user
    Date dateCreated
    Date lastUpdated

    static constraints = {
        firstName blank: false
        middleName nullable: true
        lastName blank: false
        photo nullable: true, maxSize: 2 * 1024**2
        bio nullable: true, maxSize: 500
    }

    static mapping = {
        tablePerSubclass true
    }
}

class AcademicProfile extends Profile {

    User user
    String dblpId
    String scholarId
    String website
    Date dateCreated
    Date lastUpdated

    static hasMany = [publications: Publication]

    static constraints = {
        importFrom BasicProfile
        dblpId nullable: true
        scholarId nullable: true
        website nullable: true, url: true
        publications nullable: true
    }

    static mapping = { 
        tablePerSubclass true
    }
}

Then there is a Publication class.

class Publication {

    String dblpId
    String scholarId
    String title
    String description
    Date publicationDate
    int citations
    Date dateCreated
    Date lastUpdated

    static belongsTo = [AcademicProfile]
    static hasOne = [publisher: Publisher]
    static hasMany = [academicProfiles: AcademicProfile]

    static constraints = {
        dblpId nullable: true
        scholarId nullable: true
        title blank: false, maxSize: 100
        description nullable: true, maxSize: 500
        publicationDate: nullable: true
        academicProfiles nullable: false
    }
}

Finally, I have a User class.

class User {

    String username
    String password
    String email
    Date dateCreated
    Date lastUpdated

    static hasOne = [basicProfile: BasicProfile, academicProfile: AcademicProfile]

    static constraints = {
        username size: 3..20, unique: true, nullable: false, validator: { _username ->
            _username.toLowerCase() == _username
        }
        password size: 6..100, nullable: false, validator: { _password, user ->
            _password != user.username
        }
        email email: true, blank: false
        basicProfile nullable: true
        academicProfile nullable: true
    }
}

My questions are as follows.

  1. I want a relationship where each User may optionally have a Profile (either BasicProfile or AcademicProfile). I tried static hasOne = [profile: Profile] but I got errors saying Profile does not agree to the hasOne relationship. So the current setup I have is a workaround. Is there no way a user can have one Profile be it BasicProfile or AcademicProfile?
  2. Secondly, in the current setup, I get the error: Invocation of init method failed; nested exception is org.hibernate.MappingException: An association from the table academic_profile_publications refers to an unmapped class: org.academic.AcademicProfile when I try to run it. A Google search tells me that this is a problem with classes which are inheriting from other classes. So technically, if I don't have a hasMany relationship in Publication with AcademicProfile, it should work without any issues. But I don't want that. Because a publication has many authors (AcademicProfiles in my case) and an author may have many publications. So is there a way to fix this?

回答1:


You're not using Hibernate inheritance - that requires that all of the classes be mapped. You're just using regular Java/Groovy inheritance where you inherit properties and methods from base classes. But Hibernate isn't aware of that, so it can't do queries on the unmapped base class.

I'm not sure why it's complaining about AcademicProfile, but it could be a secondary bug caused by the core issue.

I find Hibernate inheritance to be way too frustrating to use in most cases, so I use this approach when there is shared code.

It should work if you move Profile to grails-app/domain. Once you do that you should move the tablePerSubclass mapping config to the base class and only specify it once.



来源:https://stackoverflow.com/questions/26498631/relationships-between-grails-domain-classes-with-inheritance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!