其實本來沒啥大問題,但到網上查的時候發現了一些誤人子弟的說法,所以還是記下來吧。
現象:
hibernate從低版本升級到某一個版本時(我們是升到4.3.10)時,在程序啟動時會報錯:
java.lang.NoSuchMethodError: javax.persistence.Table.indexes()[Ljavax/persistence/Index;
於是查資料,網上也有許多人遇到同樣的錯誤,並且發現的原因是在model中使用了@Table(name="xxx")這個注解所致,於是推薦的改法是將這個標簽去掉,改用@Entity(name="xxx")這個注解,甚至有人說是新版的hibernate不支持@Table這個注解了。
其實不然。
在Hibernate的新新官方文檔中,明確提到了@Table這個注解:
@Table
lets you define the table the entity will be persisted into. If undefined, the table name is the unqualified class name of the entity.
當然你可以不寫這個注解,那么表名默認就是非限定類名(也就是不帶包的類名)。但企圖使用@Entity(name="xxx")來代替,把這里的xxx作為表名來看卻是大錯特錯了,@Entity中的nama屬性表示的是重新定義實體名:
@Entity.name
lets you define the shortcut name of the entity you can use in JP-QL and HQL queries. It defaults to the unqualified class name of the class.
這里的默認也是非限定類名。這個實體名就是你在Hql中使用的(比如“from xxx")那個model名稱,一般這個名稱不要重新定義,直接用類名就OK,更不要把它當做表名,除非你的表名和實體名一模一樣。
回到那個異常,這個問題如何解決呢?
可以肯定的是,這個問題是由jar包沖突引起的,hibernate的注解基礎部分現在都采用JPA的注解了,JPA是屬於javaEE的一部分,許多javaEE的包中也包括了JPA 的相關API,這個問題可能就是由於項目中存在javaEE相關的jar包,與hibernate所包含的JPA相關的jar包版本有沖突。
解決辦法一:刪除沖突的jar包
首先排查下項目Lib庫,發現類似的jar包要檢查下,比如有人發現這些包ejb3-persistence.jar,javaee.jar,可以解開看一下,如果里面有javax.persistence這個包名,估計就找到問題jar包了。處理方法要么把這些包刪除,如果一定需要,那也要升級個別的版本試試,或者把jar包里的java.persistence下樣關的內容刪除,再重新打包。
解決辦法二:針對resin服務器中的jar包沖突
但我們項目遇到了更怪僻的問題,lib庫中沒有相關的javaee包,無法用上面所說的方法。找來找去,終於發現,我們用的resin服務器,resin自帶的系統庫里有一個javaee-16.jar的包。但不論是刪除這個Jar包還是重新編譯,resin均報錯。又google出去,終於找到解決方法:
在resin.xml文件最后加上一句:
<class-loader> <servlet-hack/> </class-loader>
好使!問題終於解決!