Como ter um relacionamento @OneToMany com sua própria entidade?
-
11-07-2019 - |
Pergunta
Eu tenho itens que podem conter outros elementos, portanto, eu preciso de um relacionamento @OneToMany com a mesma entidade. Tenho configurado o meu campo assim:
@ManyToOne(targetEntity=PersistentItem.class, fetch=FetchType.EAGER)
@JoinColumn(name="ID_CHILDREN", nullable=false)
HashSet<PersistentItem> children=new HashSet<PersistentItem>();
No entanto, Java sempre lança o seguinte erro:
SEVERE: Servlet.service() for servlet HelloWorld threw exception
javax.persistence.RollbackException: java.lang.NullPointerException
Porque é que alguns itens não têm filhos?
provedor de implementação Meu JPA é EclipseLink.
EDIT: O rastreamento de pilha completo é:
03-Aug-2009 19:22:09 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet HelloWorld threw exception
javax.persistence.RollbackException: java.lang.NullPointerException
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63)
at info.lenni.gate.servlet.HelloWorld.doGet(HelloWorld.java:52)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:637)
Caused by: java.lang.NullPointerException
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.checkForUnregisteredExistingObject(UnitOfWorkImpl.java:678)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.discoverAndPersistUnregisteredNewObjects(UnitOfWorkImpl.java:4007)
at org.eclipse.persistence.mappings.ObjectReferenceMapping.cascadeDiscoverAndPersistUnregisteredNewObjects(ObjectReferenceMapping.java:743)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.cascadeDiscoverAndPersistUnregisteredNewObjects(ObjectBuilder.java:1511)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.discoverAndPersistUnregisteredNewObjects(UnitOfWorkImpl.java:4019)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.discoverUnregisteredNewObjects(RepeatableWriteUnitOfWork.java:182)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:628)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1387)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:160)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1060)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:84)
... 16 more
Solução
O seu mapeamento é definitivamente incorreto.
Primeiro de tudo, deve ser @OneToMany
, não `@ManyToOne' - você está mapeando uma coleção (ou seja, muitos). Talvez que é um erro de digitação, embora, como título da pergunta diz "OneToMany".
Em segundo lugar, a forma como é mapeado fará associação unidirecional . Isso não é uma abordagem recomendada. É você 100% positivo é isso que você quer? Pode ser melhor para mudar isso para um mapeamento bidirecional, adicionando uma propriedade "pai".
Finalmente, buscar ansioso em uma associação como esta iria puxar o toda sub-árvore quando você seleciona um item (por exemplo, item em si, seus filhos, seus filhos, etc ...) Embora existam algumas circunstâncias em que pode ser desejável, eles são bastante incomum. Você realmente quer que o comportamento? Talvez seria melhor usar um modelo diferente (como conjuntos aninhados)?
Outras dicas
O que você pretende, definindo anulável a falsa?
@JoinColumn(name="ID_CHILDREN", nullable=false)
Se alguns itens não podem ter filhos é mesmo?