2016-01-26 53 views
0

给定具有以下列的表:带外键的Hibernate表参考同一个表非主列返回无结果

ID | parent_api_id | api_id

其中parent_api_id应引用与OneToMany关系相同的表的api_id:一个条目应该只有一个父代,但可能有任何引用它的正数的下属。

我有以下设置:

@Entity 
@Table(name="regions") 
publicclass Region { 

    private Integer id; 
    private Region parent; 
    private Integer apiId; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "id", nullable = false, unique = true) 
    public Integer getId() { 
     return id; 
    } 

    public Region setId(Integer id) { 
     this.id = id; 
     return this; 
    } 

    @ManyToOne 
    @JoinColumn(name = "parent_api_id", referencedColumnName = "api_id") 
    public Region getParent() { 
     return parent; 
    } 

    public Region setParent(Region parent) { 
     this.parent = parent; 
     return this; 
    } 

    @Column(name="api_id") 
    public Integer getApiId() { 
     return apiId; 
    } 

    public Region setApiId(Integer apiId){ 
     this.apiId = apiId; 
     return this; 
    } 
} 

该类会给没有结果,也没有例外,而我期望看到许多返回结果。

如果我注释掉在父注释:

//@ManyToOne 
//@JoinColumn(name = "parent_api_id", referencedColumnName = "api_id") 
public Region getParent() { 
    return parent; 
} 

相同的操作将返回我的期望,只是没有父母的信息来源。

如果我有:

@ManyToOne 
@JoinColumn(name = "parent_api_id")//, referencedColumnName = "api_id") 
public Region getParent() { 
    return parent; 
} 

然后,它会抛出异常:

org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [my.app.Region#6131153] 
at org.hibernate.impl.SessionFactoryImpl$1.handleEntityNotFound(SessionFactoryImpl.java:375) 
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:145) 
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:195) 
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:103) 
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878) 
at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:846) 
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:557) 
at org.hibernate.type.EntityType.resolve(EntityType.java:379) 
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:116) 
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:842) 
at org.hibernate.loader.Loader.doQuery(Loader.java:717) 
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224) 
at org.hibernate.loader.Loader.doList(Loader.java:2211) 
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2095) 
at org.hibernate.loader.Loader.list(Loader.java:2090) 
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:95) 
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1569) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:497) 
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:301) 
at com.sun.proxy.$Proxy31.list(Unknown Source) 
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:283) 
at com.wewherego.api.malloc.domain.repositories.PlaceRepository.invokeQuery(PlaceRepository.java:81) 
at com.wewherego.api.malloc.domain.repositories.PlaceRepository.search(PlaceRepository.java:50) 
at com.wewherego.api.malloc.controllers.RegionsController.search(RegionsController.java:50) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:497) 
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215) 
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132) 
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) 
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781) 
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721) 
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83) 
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943) 
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877) 
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966) 
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621) 
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
at com.wewherego.api.malloc.infrastructure.CORSFilter.doFilter(CORSFilter.java:23) 
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:222) 
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) 
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) 
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) 
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100) 
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) 
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) 
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) 
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041) 
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603) 
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
at java.lang.Thread.run(Thread.java:745) 

这也是我理解为什么:它默认为寻找的#6023506 ID而不是api_id,而它实际上假设映射到api_id。

所以在我的第一种方法中,我做错了什么?

+0

您是否在保存'Region'实体的同时设置了'parent'实例变量,并且您是否看到在DB表中存在?如果它持续存在,则让Region类实现'Serializable'并尝试。 –

+0

我从数据库检索时发现错误,而不是写入。 – jamesdeath123

+0

你能发布异常吗? –

回答

0

使Region类实现Serializable应该有所帮助。

从JBoss的文档linkwhen using referencedColumnName to a non primary key column, the associated class has to be Serializable.

使得该地区一流的序列化的报价如下:

@Entity 
@Table(name="regions") 
class Region implements Serializable{ 

    private Integer id; 
    private Region parent; 
    private Integer apiId; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "id", nullable = false, unique = true) 
    public Integer getId() { 
     return id; 
    } 

    @ManyToOne 
    @JoinColumn(name = "parent_api_id", referencedColumnName = "api_id") 
    public Region getParent() { 
     return parent; 
    } 
// Remaining getters/setters 
} 

而与此我看到,我能够检索区的对象与正确填充parent_api_id和api_id与以下测试代码。

 Session session = openSession(); 
     Transaction tx = session.beginTransaction(); 
     Region r1 = new Region(); 
     r1.setApiId(40); 
     session.persist(r1); 

     Region r2 = new Region(); 
     r2.setApiId(20); 
     r2.setParent(r1); 

     Region r3 = new Region(); 
     r3.setApiId(30); 
     r3.setParent(r1); 

     session.persist(r2); 
     session.persist(r3); 
     tx.commit(); 

     Session session1 = openSession(); 
     Transaction tx1 = session1.beginTransaction(); 
     Region r = session1.get(Region.class, r3.getId()); 
     //OR Region r = (Region) session1.createCriteria(Region.class).add(Restrictions.eq("id", r3.getId())).uniqueResult(); 

结果在下面的连接查询

select 
    region0_.id as id1_0_0_, 
    region0_.api_id as api_id2_0_0_, 
    region0_.parent_api_id as parent_a3_0_0_, 
    region1_.id as id1_0_1_, 
    region1_.api_id as api_id2_0_1_, 
    region1_.parent_api_id as parent_a3_0_1_ 
from 
    regions region0_ 
left outer join 
    regions region1_ 
     on region0_.parent_api_id=region1_.api_id 
where 
    region0_.id=? 

输出地区的ID - 3,区API ID - 30,父ID - 1,家长API ID - 40

希望我有不会误解这个问题。

相关问题