двунаправленное сопоставление OneToOne: от сущности к подклассу и от суперкласса к сущности?

Я пытаюсь установить хитрое двунаправленное сопоставление OneToOne в спящем режиме. Я получил следующие классы:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Parent {
     @OneToOne
     private AnotherEntity anotherEntity;
}
@Entity
public class Child1 extends Parent{}

@Entity
public class Child2 extends Parent{}

@Entity
public class AnotherEntity {

    @OneToOne(mappedBy = "anotherEntity")
    private Child1 child1;
    @OneToOne(mappedBy = "anotherEntity")
    private Child2 child2;
}

Проблема здесь в том, что когда я запускаю приложение: я получил следующее сообщение:

org.hibernate.MappingException: property [anotherEntity] not found on entity [Child1]
    at org.hibernate.mapping.PersistentClass.getRecursiveProperty(PersistentClass.java:429)
    at org.hibernate.mapping.PersistentClass.getReferencedProperty(PersistentClass.java:369)
    at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1614)
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1362)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1727)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1778)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:189)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:350)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:335)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:567)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
    at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:631)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:588)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:645)
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:508)
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:449)
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:133)
    at javax.servlet.GenericServlet.init(GenericServlet.java:160)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1266)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1185)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1080)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5015)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5302)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:895)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:871)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:962)
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:536)
    at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1471)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:301)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:836)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:761)
    at org.apache.catalina.manager.ManagerServlet.check(ManagerServlet.java:1436)
    at org.apache.catalina.manager.ManagerServlet.deploy(ManagerServlet.java:673)
    at org.apache.catalina.manager.ManagerServlet.doPut(ManagerServlet.java:431)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:644)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:581)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)

Одним из очевидных решений было бы переместить поле anotherEntity в Child1 и Child2, но это означало бы потерю связи с Parent на AnotherEntity.

Приветствуется любая помощь.


person Teocali    schedule 05.07.2012    source источник
comment
Можем ли мы увидеть полную трассировку стека? У меня возникли проблемы с воспроизведением ошибки.   -  person jeff    schedule 05.07.2012
comment
Добавлена ​​полная трассировка стека исключений. Кроме того, я использую Spring для настройки спящего режима, и это веб-приложение на сервере tomcat, но я не думаю, что это актуально   -  person Teocali    schedule 06.07.2012
comment
Я обнаружил, что проблема может исходить от наследства. Когда я удаляю строку @Inheritance(strategy = InheritanceType.JOINED) и переключаюсь на стратегию наследования одной таблицы (по умолчанию), у меня больше нет проблем.   -  person Teocali    schedule 06.07.2012
comment
Я не очень ясно выразился в своем последнем комментарии, но изменение стратегии не является возможным решением, поэтому я все еще застрял   -  person Teocali    schedule 07.07.2012


Ответы (1)


Короткий ответ: вы не можете (с Hibernate).

Во-первых, не совсем понятно, чего вы пытаетесь достичь с помощью приведенного примера. Вы указали, что хотите, чтобы AnotherEntity имел два свойства типа Child1. Я предполагаю, что вы на самом деле хотите по одному из каждого, Child1 и Child2. Кроме того, вы используете один и тот же mappedBy = "anotherEntity" для обоих свойств, вы действительно имеете в виду, что вам нужны две ссылки на Parent на otherEntity? В любом случае это помогает проиллюстрировать проблему в ситуации такого типа:

Вы указали InheritanceType.JOINED, что означает, что внешний ключ для Parent -> AnotherEntity находится в любой таблице, с которой сопоставлен класс Parent. В этом случае Hibernate не может различать два ваших подтипа, он должен зависеть исключительно от типа, указанного в вашем классе Java, - это определенно может привести к проблемам.

По-видимому, другие поставщики JPA могут поддерживать такое поведение (но вы можете понять, почему Hibernate решил этого не делать и почему вам нужно быть осторожным с ним). Для справки см. этот аналогичный вопрос SO и различные обсуждения на форумах Hibernate/JIRA:

person David    schedule 09.07.2012
comment
Хорошо, спасибо за ответ. Я обходился без него до сих пор, и я буду продолжать. - person Teocali; 09.07.2012