2012-10-17 51 views
0

我使用Hibernate 4.1.7 Java與Spring,在MySql上工作。休眠雙向OneToMany與JoinTable和多態類與表每個具體類

我有一個出版類,它是抽象的,有3個子類,Page類也是抽象的,有2個子類。

在文章有一個列表,並在頁面我有一個公開,所以這是一個常見的一對多/多對一雙向關係,但因爲我需要我使用的是交叉表進行排序的頁面,如圖所示:

// Publication.java 
@OneToMany(fetch=FetchType.LAZY) 
@JoinTable(name="publication_pages", 
      [email protected](table="publication_pages", name="pub_id", referencedColumnName="id"), 
      [email protected](table="publication_pages", name="pg_id", referencedColumnName="id")) 
@OrderColumn(name="i") 
public List<Page> getPages() { 
    return pages; 
} 

// Page.java 

@ManyToOne 
@JoinTable(name="publication_pages", 
     [email protected](table="publication_pages", name="pg_id", referencedColumnName="id", insertable=false, updatable=false), 
     [email protected](table="publication_pages", name="pub_id", referencedColumnName="id", insertable=false, updatable=false)) 
public Publication getPublication() { 
    return publication; 
} 

Hibernate不會抱怨註釋,但只要我嘗試調用getPages,它就會生成一個查詢,以便在頁子類表上搜索pub_id,而不是僅在交叉表中。

的錯誤是:

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'page1_.pub_id' in 'field list' 
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) 
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
at java.lang.reflect.Constructor.newInstance(Constructor.java:532) 
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) 
at com.mysql.jdbc.Util.getInstance(Util.java:386) 
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1053) 
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4074) 
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4006) 
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2468) 
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2629) 
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2719) 
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155) 
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2318) 
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeQuery(NewProxyPreparedStatement.java:76) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:616) 
at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122) 
at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81) 
at $Proxy54.executeQuery(Unknown Source) 
at org.hibernate.loader.Loader.getResultSet(Loader.java:1897) 
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1698) 
at org.hibernate.loader.Loader.doQuery(Loader.java:832) 
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:293) 
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:263) 
at org.hibernate.loader.Loader.loadCollection(Loader.java:2094) 
at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:61) 
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:678) 
at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:82) 
at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1801) 
at org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:524) 
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:212) 
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:520) 
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:125) 
at org.hibernate.collection.internal.AbstractPersistentCollection$1.doWork(AbstractPersistentCollection.java:152) 
at org.hibernate.collection.internal.AbstractPersistentCollection$1.doWork(AbstractPersistentCollection.java:139) 
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:212) 
at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:138) 
at org.hibernate.collection.internal.PersistentList.isEmpty(PersistentList.java:121) 

的我做錯了什麼,或者是一個Hibernate的錯誤,或者是根本不可能的,由於大量的工會它執行的查詢?

TIA

編輯:這是查詢Hibernate是生成(我刪除了所有不相關的列):

Hibernate: 
select 
pages0_.pub_id as pub1_46_3_, 
pages0_.pg_id as pg2_43_3_, 
pages0_.i as i3_, 
page1_.id as id42_0_, 
[...] 
page1_.pub_id as pub1_43_0_ [...] 

from publication_pages pages0_ 
inner join ( 
    select id, [...] from page_fixed union select id, [...] from page_query 
) page1_ 

on pages0_.pg_id=page1_.id left outer join ( 
    select id, [...] from publication 
) publicatio2_ 
on page1_.pub_id=publicatio2_.id left where pages0_.pub_id=? 

正如你所看到的,它使用page1_.pub_id在加入(就好像pub_id在Page上)而不是pages0_.pub_id(在where子句中正確使用)。

這發生在以Publication.getPages()的調用。的isEmpty()

+0

爲什麼你使用交叉表進行排序?您是否考慮過在Page類中實現Comparable接口,並使用'@Sort(type = SortType.NATURAL)'在出版物中註釋頁面列表? –

+0

因爲我需要getPages()集合是有序的(一個頁面將成爲發佈的第一頁,另一個是第二個頁面等等),並且DDL被設計爲一個交叉表。但是我認爲,如果我們設法保持「排序列表」行爲,我可以同意其他人擺脫交叉表。 Comparable似乎不是一個選項,因爲它需要一個Page.getPageNumber,必須在代碼中「手動」處理,而不是依賴List。 –

+1

我用hibernate 4.1.7測試了你的代碼,並且調用了publication.getPages()並沒有導致錯誤 - 很奇怪。 Hibernate生成以下查詢:'Select pages0_.pub_id as pub1_8_2_,pages0_.pg_id as pg2_6_2_,pages0_.i as i2_,page1_.id as id5_0_,page1_1_.pub_id as pub1_6_0_,publicatio2_.id as id8_1_ from publication_pages page0_ inner join page1__ on page0_.pg_id = page1_.id left outer join publication_pages page1_1_ on page1_.id = page1_1_.pg_id left outer join publicatio2_ on page1_1_.pub_id = publicatio2_.id where page0_.pub_id =?' –

回答

0

也許,你可以一個mappedBy添加到您的@OneToMany並刪除其@JoingTable。與OneToMany/ManyToOne的雙向關係不需要雙方都有@JoingTable,您只需要關係所有者。