Java Hibernate get parent';子实体的s id

Java Hibernate get parent';子实体的s id,java,hibernate,jpa-2.0,spring-data-jpa,Java,Hibernate,Jpa 2.0,Spring Data Jpa,很多人都发布过类似的问题,但我似乎找不到一个能解决我的情况的 我有一个父实体Dnar和一个子实体WorkLocationSuburb。Dnar具有一对多工作位置子城市 通常,我会将这种关系定义如下: 孩子 @Entity @Table(name = "req_work_suburb", schema = SCHEMA) public class WorkLocationSuburb { @Id @GeneratedValue(generator = "req_work_suburb_s

很多人都发布过类似的问题,但我似乎找不到一个能解决我的情况的

我有一个父实体
Dnar
和一个子实体
WorkLocationSuburb
Dnar
具有一对多
工作位置子城市

通常,我会将这种关系定义如下:

孩子

@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
}
@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
}
父项

@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
}
@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
}
当我执行上述操作时,我得到以下异常:

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
它似乎失败了,因为Hibernate在
WorkLocationSuburb
上找不到名为
DNAND
的属性。我的问题是,如何将这些信息添加到
WorkLocationSuburb
,而不让Hibernate抱怨其他问题?似乎我需要一些代码,如:

@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
}
有人知道我怎样才能让上面的附加专栏发挥作用吗?此列必须自动填充父级的
dnand

谢谢, 穆尔


更新了JB Nizet的建议

我的代码现在是这样的:

孩子

@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
}
@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
}
父项

@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
}
@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
}
@实体
@表(name=“req_dnar”,schema=schema)
@继承(策略=加入)
@鉴别器列(name=“form\u type”,鉴别器类型=字符串,长度=64)
公共抽象类Dnar{
@身份证
@GeneratedValue(generator=“需求数据顺序”)
@GenericGenerator(strategy=“sequence”,name=“req_dnar_seq”,parameters={@Parameter(name=“sequence”,value=SCHEMA+”.req_dnar_seq”)})
@列(name=C\u DNAR\u ID,null=false)
私人长途电话;
@列(名称=“原始id”)
私人长源代码;
@OneToMany(cascade=ALL,fetch=EAGER,orphaneremovation=true,mappedBy=“dnar”)
private Set workLocationSuburbs=new LinkedHashSet();
@后复印机
void setChildRefs(){
对于(WorkLocationSuburb郊区:workLocationSuburbs){
郊区。塞德纳尔(本);
}
}
//省略的余数
}
当我尝试保存附加了
WorkLocationSuburb
Dnar
时,我会看到以下事件顺序:

  • Dnar
    插入数据库
  • 调用
    @PostConstuct
    ,并且
    WorkLocationSuburb
    获取对父
    Dnar
    的引用。父级
    Dnar
    已正确分配ID
  • 尝试插入子
    WorkLocationSuburb
    ,但导致以下异常:org.hibernate.exception.ConstraintViolationException:ORA-01400:无法将NULL插入(“DNAR”。“请求工作郊区”。“DNAR\U ID”)`

  • 我还在错误地做什么?:)

    您只需将关联设置为双向:

    public class WorkLocationSuburb {
        @ManyToOne
        @JoinColumn
        private Dnar parentDnar;
        // ...
    }
    
    public class Dnar {
        @OneToMany(mappedBy = "parentDnar", ...)
        private Set<WorkLocationSuburb> suburbs;
        // ...
    }
    
    类似地,如果从dnar中删除郊区,则应将郊区的parentDnar设置为null


    关于查询,现在可以在查询中使用
    parentDnar
    字段。记住,JPA查询总是在实体及其持久字段/属性上工作。从不在表及其列上使用。我尝试了您的建议,但Hibernate不知道如何在子实体上填充外键列。请问我错过了什么?哦,我在上面的问题中添加了我尝试过的代码。试着不要使用PostPersist钩子来设置父ID。我很确定在这种回调方法中不应该修改实体。只需将其封装在实体或服务方法中即可。谢谢,伙计,这就解决了它!