问题
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.
- I want a relationship where each
Usermay optionally have aProfile(eitherBasicProfileorAcademicProfile). I triedstatic hasOne = [profile: Profile]but I got errors sayingProfiledoes not agree to thehasOnerelationship. So the current setup I have is a workaround. Is there no way a user can have oneProfilebe itBasicProfileorAcademicProfile? - 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.AcademicProfilewhen 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 ahasManyrelationship inPublicationwithAcademicProfile, 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