2012-11-22 3 views
2

으로부터 부모의 ID를 얻는다. 많은 사람들이 비슷한 문제를 게시했지만, 나는 내 상황을 해결할 수없는 것을 발견 할 수 없다.Hibernate는 하위 엔티티

나는 부모 엔티티 Dnar와 아이 엔티티 WorkLocationSuburb 있습니다. Dnar은 일대 다 WorkLocationSuburbs입니다.

아이

@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_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 
} 

는 위의 예제가 작동하는 부모, 그리고 때 수동으로 쿼리를 다음과 같이

일반적으로, 나는이 관계를 정의 할 req_work_suburb 테이블, 나는 그것이를 가지고있는 것을 볼 수있다.열과 열이 올바르게 채워지고 있는지 확인하십시오. 모두 좋다, 지금까지!

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 

그것을 : 나는 위 실행하면

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))); 
     } 
    }; 
    } 

, 나는 다음과 같은 예외를 얻을 : 일부 쿼리 코드에서

, 나는 req_work_suburb.dnar_id의 값에 의존하는 기준 쿼리를 만들 Hibernate가 에 dnarId이라는 속성을 찾을 수 없기 때문에 실패한 것 같습니다. 제 질문은, 어떻게 다른 문제에 대해 불평하고 최대 절전 모드없이이 정보를 WorkLocationSuburb에 추가 할 수 있습니까? 그것은 같은 코드가 필요해 보이는 :

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

누구든지 내가 위의 추가 열을 어떻게 작동시키는 지 알 수 있습니까? 이 열 이어야하며 부모의 dnarId으로 자동 입력되어야합니다.

감사합니다, Muel.


는 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; 

    @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, mappedBy="dnar") 
    private Set<WorkLocationSuburb> workLocationSuburbs = new LinkedHashSet<WorkLocationSuburb>(); 


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

    //remainder omitted 
} 

나는 WorkLocationSuburb, 나는 다음과 같은 이벤트 순서를 참조 붙어있는 Dnar 저장하려고하면 :

  1. Dnar
  2. @PostConstuct가 호출되는 데이터베이스에 삽입하고 WorkLocationSuburb가를 얻을 수를 부모 Dnar에 대한 참조. 부모 Dnar에 ID가 올바르게 지정되었습니다.
  3. 아이 WorkLocationSuburb의 삽입을 시도하지만, 다음과 같은 예외 결과 : org.hibernate.exception.ConstraintViolationException가 : ORA-01400이 : (.. "DNAR" "REQ_WORK_SUBURB" "DNAR_ID")에`
  4. 를 NULL을 삽입 할 수 없습니다

내가 아직도 잘못하고있는 것은 무엇입니까? :)

당신은 협회의 양방향해야

답변

2

:

public class WorkLocationSuburb { 
    @ManyToOne 
    @JoinColumn 
    private Dnar parentDnar; 
    // ... 
} 

public class Dnar { 
    @OneToMany(mappedBy = "parentDnar", ...) 
    private Set<WorkLocationSuburb> suburbs; 
    // ... 
} 

그냥 양방향 OneToMany 협회에서 협회의 소유면이 많은 쪽 (하지 않는면이 항상 있다는 인식을 mappedBy 속성을 가짐). 이것은 Hibernate가 연관이 존재 하는지를 결정하기 위해서 WorkLocationSuburb.parentDnar 필드만을 고려할 것임을 의미한다. 당신은, 당신은에 교외의 parentDnar을 설정해야 dnar에서 교외를 제거하면,

public void addSuburb(WorkLocationSuburb suburb) { 
    this.suburbs.add(suburb); 
    suburb.setParentDnar(this); 
} 

마찬가지로이 따라서, 당신은 또한 교외의 dnar 필드를 설정해야 할 때마다 당신이 dnar에 교외를 추가하는 것을 의미한다 없는.

쿼리와 관련하여 쿼리에서 parentDnar 필드를 사용할 수 있습니다. JPA 쿼리는 항상 엔티티 및 해당 영구 필드/속성에서 작동한다는 점을 기억하십시오. 절대로 테이블과 칼럼에서.

+0

나는 당신의 제안을 시도했지만, Hibernate는 하위 엔티티에 외래 키 컬럼을 채우는 방법을 이해하지 못한다. 내가 놓친 게 뭐야? 아, 그리고 위의 질문에 시도한 코드를 추가했습니다. – Muel

+0

PostPersist 후크를 사용하여 상위 ID를 설정하지 마십시오. 콜백 메소드에서 엔티티를 수정하지 않아도된다고 확신합니다. 엔티티 또는 서비스 메소드에 캡슐화하면됩니다. –

+0

고마워, 고쳐! – Muel

관련 문제