Hibernate get parent-id aus der untergeordneten Entität

viele Leute gepostet haben sehr ähnliche Probleme, aber ich kann nicht scheinen, einen zu finden, der meine Adressen Umstand.

Habe ich eine übergeordnete Entität Dnar - und einer untergeordneten Entität WorkLocationSuburb. Ein Dnar eins-zu-viele -WorkLocationSuburbs.

Normalerweise würde ich definieren dieses Verhältnis wie folgt:

Das Kind

@Entity
@Table(name = "req_work_suburb", schema = SCHEMA)
public class WorkLocationSuburb {

  @Id
  @GeneratedValue(generator = "req_work_suburb_seq")
  @GenericGenerator(strategy="sequence", name="req_work_suburb_seq", parameters={@Parameter(name="sequence", value=SCHEMA+".req_work_suburb_seq")})
  @Column(name = "id", nullable = false)
  private Long id;

  @Column(name="suburb", length=255, nullable=false)
  private String suburb;

  //remainder omitted
}

Die Eltern

@Entity
@Table(name = "req_dnar", schema = SCHEMA)
@Inheritance(strategy = JOINED)
@DiscriminatorColumn(name = "form_type", discriminatorType = STRING, length = 64)
public abstract class Dnar {

  @Id
  @GeneratedValue(generator = "req_dnar_seq")
  @GenericGenerator(strategy = "sequence", name = "req_dnar_seq", parameters = { @Parameter(name = "sequence", value = SCHEMA + ".req_dnar_seq") })
  @Column(name = C_DNAR_ID, nullable = false)
  private Long dnarId;

  @Column(name = "original_id")
  private Long originalId;


  @OneToMany(cascade = ALL, fetch = EAGER, orphanRemoval=true)
  @JoinColumn(name = "dnar_id", nullable=false)
  private Set<WorkLocationSuburb> workLocationSuburbs;

  //remainder omitted
}

Funktioniert das obige Beispiel, und wenn ich manuell Abfrage der req_work_suburb Tisch, ich kann sehen, dass es dnar_id Spalte und die Spalte ist korrekt aufgefüllt. Alles gut, so weit!

In einigen Abfrage-code, erstelle ich eine criteria-Abfrage, die in Abhängigkeit vom Wert des req_work_suburb.dnar_id:

  private static Specification<SubmittedDnarSummary> suburbIs(final String suburb) {
    return new Specification<SubmittedDnarSummary>(){
      @Override
      public Predicate toPredicate(Root<SubmittedDnarSummary> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        Subquery<Long> subquery = query.subquery(Long.class);
        Root<WorkLocationSuburb> suburbRoot = subquery.from(WorkLocationSuburb.class);
        return cb.in(root.get("dnarId")).value(subquery.select(suburbRoot.<Long>get("dnarId")).where(cb.equal(suburbRoot.get("suburb"), suburb)));
      }
    };
  }

Wenn ich führen Sie die oben, bekomme ich die folgende exception:

org.springframework.dao.InvalidDataAccessApiUsageException: Unable to resolve attribute [dnarId] against path; nested exception is java.lang.IllegalArgumentException: Unable to resolve attribute [dnarId] against path
         at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:301)
         at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:106)
         at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:403)
         at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58)
         at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
         at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163)
         at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
         at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:91)
         at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
         at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
         at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
         at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
         at $Proxy253.findAll(Unknown Source)
         at au.com.wpcorp.sys.dnar.spring.manager.impl.SearchManagerImpl.search(SearchManagerImpl.java:66)
         at au.com.wpcorp.sys.dnar.spring.mvc.controller.search.DnarSearchController.results(DnarSearchController.java:97)
         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.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
         at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
         at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
         at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
         at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
         at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
         at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
         at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
         at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
         at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
         at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
         at javax.servlet.http.HttpServlet.service(HttpServlet.java:770)
         at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
         at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
         at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
         at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
         at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
         at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
         at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
         at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
         at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
         at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
         at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
         at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
         at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
         at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
         at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
         at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
         at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
         at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
         at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
         at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
         at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
         at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
         at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
         at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.IllegalArgumentException: Unable to resolve attribute [dnarId] against path
         at org.hibernate.ejb.criteria.path.AbstractPathImpl.unknownAttribute(AbstractPathImpl.java:118)
         at org.hibernate.ejb.criteria.path.AbstractPathImpl.locateAttribute(AbstractPathImpl.java:223)
         at org.hibernate.ejb.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:194)
         at au.com.wpcorp.sys.dnar.spring.manager.impl.SearchManagerImpl$3.toPredicate(SearchManagerImpl.java:141)
         at org.springframework.data.jpa.repository.support.SimpleJpaRepository.applySpecificationToCriteria(SimpleJpaRepository.java:480)
         at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:436)
         at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:421)
         at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:303)
         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.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:334)
         at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:319)
         at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
         at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
         at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
         at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
         ... 49 more

Scheint es zu scheitern, weil Hibernate nicht finden können, eine Eigenschaft, die man als dnarId auf WorkLocationSuburb. Meine Frage ist, wie kann ich diese Informationen hinzuzufügen, um WorkLocationSuburb ohne Hibernate Klagen über ein anderes problem? Es scheint, ich brauche ein paar Codes wie:

@Entity
@Table(name = "req_work_suburb", schema = SCHEMA)
public class WorkLocationSuburb {

  @Id
  @GeneratedValue(generator = "req_work_suburb_seq")
  @GenericGenerator(strategy="sequence", name="req_work_suburb_seq", parameters={@Parameter(name="sequence", value=SCHEMA+".req_work_suburb_seq")})
  @Column(name = "id", nullable = false)
  private Long id;

  @Column(name="suburb", length=255, nullable=false)
  private String suburb;

  @Column(name="dnar_id", nullable=false)  //column definition added here
  private Long dnarId;

  //remainder omitted
}

Weiß jemand, wie kann ich die oben genannten zusätzlichen Spalte arbeiten? Diese Spalte muss automatisch mit den Eltern dnarId.

Dank,
Muel.


Aktualisiert mit JB Nizet Anregungen

Mein code ist jetzt so:

Das Kind

@Entity
@Table(name = "req_work_suburb", schema = SCHEMA)
public class WorkLocationSuburb {

  @Id
  @GeneratedValue(generator = "req_work_suburb_seq")
  @GenericGenerator(strategy="sequence", name="req_work_suburb_seq", parameters={@Parameter(name="sequence", value=SCHEMA+".req_work_suburb_seq")})
  @Column(name = "id", nullable = false)
  private Long id;

  @Column(name="suburb", length=255, nullable=false)
  private String suburb;

  @ManyToOne
  @JoinColumn(name="dnar_id", nullable=false)
  private Dnar dnar;

  //remainder omitted
}

Die Eltern

@Entity
@Table(name = "req_dnar", schema = SCHEMA)
@Inheritance(strategy = JOINED)
@DiscriminatorColumn(name = "form_type", discriminatorType = STRING, length = 64)
public abstract class Dnar {

  @Id
  @GeneratedValue(generator = "req_dnar_seq")
  @GenericGenerator(strategy = "sequence", name = "req_dnar_seq", parameters = { @Parameter(name = "sequence", value = SCHEMA + ".req_dnar_seq") })
  @Column(name = C_DNAR_ID, nullable = false)
  private Long dnarId;

  @Column(name = "original_id")
  private Long originalId;

  @OneToMany(cascade = ALL, fetch = EAGER, orphanRemoval=true, mappedBy="dnar")
  private Set<WorkLocationSuburb> workLocationSuburbs = new LinkedHashSet<WorkLocationSuburb>();


  @PostPersist
  void setChildRefs() {
    for (WorkLocationSuburb suburb : workLocationSuburbs) {
      suburb.setDnar(this);
    }
  }

  //remainder omitted
}

Wenn ich Versuch zu speichern eine Dnar hat eine WorkLocationSuburb befestigt, sehe ich die folgende Reihenfolge der Ereignisse:

  1. Die Dnar wird in die Datenbank eingefügt
  2. @PostConstuct aufgerufen, und die WorkLocationSuburb bekommt eine Referenz auf das parent -Dnar. Die Eltern Dnar wurde eine ID zugewiesen, richtig.
  3. Die Einfügung des Kindes WorkLocationSuburb versucht, aber die Ergebnisse in die folgende exception: org.hibernate.Ausnahme.ConstraintViolationException: ORA-01400: cannot insert NULL into ("DNAR"."REQ_WORK_SUBURB"."DNAR_ID")`

Was bin ich eigentlich noch falsch? 🙂

InformationsquelleAutor Muel | 2012-11-22
Schreibe einen Kommentar