Hibernate MappingException с наследованием конкретного недоменного класса в Grails

Сценарий

Мне нужно представить объект в двух разных контекстах. Один контекст не должен сохраняться, а другой должен. Постоянные объекты являются фактическими данными, полученными из другой системы. Непостоянные объекты представляют части определения продукта. Эти два будут сравниваться, и я не заинтересован в сохранении данных определения. Постоянный объект должен иметь дополнительную информацию, хранящуюся в нем.

Реализация

Для этого я решил, что наиболее логичным будет создать базовый класс в папке src/groovy, чтобы grails / hibernate не захотел сохранить его как класс домена.

class Resource{
    String name
    Date lastModified 
}

Класс домена, который я хочу сохранить, выглядит следующим образом.

class OwnedResource extends Resource{  
  Date dateCreated, lastUpdated
  Owner owner
  static belongsTo = [owner: Owner]
  static mapping = {
   //I assumed I would need this so that grails would not expect 
   //to store the object in the base class table that doesn't exist
   tablePerHierarchy true 
   table 'owned_resource'
  }
}

Наконец, у нас есть класс Owner, у которого есть много OwnedResources.

class Owner{
  Date dateCreated, lastUpdated
  String name
  static hasMany = [
    resources: OwnedResource
  ]
}

Эта проблема

Когда я запускаю приложение, я получаю дружественное исключение Hibernate:

2011-10-24 20:32:01,307 [main] ERROR context.GrailsContextLoader  - Error executing bootstraps: 
Error creating bean with name 'messageSource': Initialization of bean failed; nested exception 
is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean 
property 'sessionFactory'; nested exception is 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
'sessionFactory': Invocation of init method failed; nested exception is 
org.hibernate.MappingException: Association references unmapped class: OwnedResource

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
'messageSource': Initialization of bean failed; nested exception is 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean 
property 'sessionFactory'; nested exception is 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
'sessionFactory': Invocation of init method failed; nested exception is 
org.hibernate.MappingException: Association references unmapped class: OwnedResource
at org.grails.tomcat.TomcatServer.start(TomcatServer.groovy:212)
at grails.web.container.EmbeddableServer$start.call(Unknown Source)
at _GrailsRun_groovy$_run_closure5_closure12.doCall(_GrailsRun_groovy:158)
at _GrailsRun_groovy$_run_closure5_closure12.doCall(_GrailsRun_groovy)
at _GrailsSettings_groovy$_run_closure10.doCall(_GrailsSettings_groovy:280)
at _GrailsSettings_groovy$_run_closure10.call(_GrailsSettings_groovy)
at _GrailsRun_groovy$_run_closure5.doCall(_GrailsRun_groovy:149)
at _GrailsRun_groovy$_run_closure5.call(_GrailsRun_groovy)
at _GrailsRun_groovy.runInline(_GrailsRun_groovy:116)
at _GrailsRun_groovy.this$4$runInline(_GrailsRun_groovy)
at _GrailsRun_groovy$_run_closure1.doCall(_GrailsRun_groovy:59)
at RunApp$_run_closure1.doCall(RunApp.groovy:33)
at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
at gant.Gant$_dispatch_closure7.doCall(Gant.groovy:415)
at gant.Gant$_dispatch_closure7.doCall(Gant.groovy)
at gant.Gant.withBuildListeners(Gant.groovy:427)
at gant.Gant.this$2$withBuildListeners(Gant.groovy)
at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
at gant.Gant.dispatch(Gant.groovy:415)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.executeTargets(Gant.groovy:590)
at gant.Gant.executeTargets(Gant.groovy:589)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.MappingException: Association references unmapped class: OwnedResource
... 24 more

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.MappingException: Association references unmapped class: OwnedResource
... 24 more

Caused by: org.hibernate.MappingException: Association references unmapped class: OwnedResource
... 24 more

Возможно, моя реализация - плохая практика, так как после долгих поисков в Google и поиска в Stackru мне еще не приходилось сталкиваться с кем-то, кто сталкивался с такой же проблемой или пытался подобной реализации. Большинство людей пытаются использовать абстрактные классы, которые действительно работают. Я хочу, чтобы класс Resource был конкретным, потому что мне нужно создать его экземпляр. Ответ может просто состоять в том, что Grails не позволяет эту функциональность, но я хотел бы услышать окончательный ответ и любые возможные обходные пути. Я склонен к тому, чтобы дублировать класс вместо использования наследования.

Что я делаю не так и почему происходит эта ошибка? Можно ли сделать эту реализацию в Grails?

2 ответа

В этом случае, если вы пытаетесь расширить класс, который находится вне папки домена, вы должны объявить этот класс как абстрактный.

В противном случае Hibernate попытается сопоставить его, и поскольку он не находится в папке домена, все в конечном итоге взорвется.

Используйте абстрактный базовый класс Resource, а затем добавьте 3-й класс, расширяющий Resource, который не является объектом домена, а представляет собой простой служебный класс, который можно использовать для других целей, не беспокоясь о постоянстве. Удачи... Дмитрий.

Другие вопросы по тегам