spring升級到3.1.1 hibernate升級到4備忘

iteye_13803發表於2012-04-03
年初兩個版本剛剛釋出,還處於“血淋淋”的邊緣,花了兩天時間把所做的基於sh的一個框架進行升級,其過程有些糾結,寫在這裡做一備忘。

為什麼要升級?升級的理由一個是hibernate4支援multi-tenant多租戶模式,對於提供saas應用的專案來說,有這個與沒這個有很大不同,儘管我已經在一個專案中實現了多租戶模式,跟hibernate要做的第二種模式類似;另一個理由就是spring支援servlet3.0,並且對提供cache api,速度當然是主要考慮點。

沒想到遇到很多問題,按網路流行語說是有點“蛋疼”。

幸虧框架是用maven進行管理,升級版本過程比較順利,主要改寫pom中的依賴:
hibernate pom dependency:


<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.1.1.Final</version>
</dependency>


spring pom dependency:


<properties>
<spring.version>3.1.1.RELEASE</spring.version>
</properties>
....
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>


注意maven2的repository還沒有最新版本,需要配置:


<repository>
<id>springsource-repo</id>
<name>springsource repository</name>
<url>http://repo.springsource.org/release</url>
</repository>

<repository>
<id>repository.jboss.org-public</id>
<name>JBoss repository</name>
<url>https://repository.jboss.org/nexus/content/groups/public</url>
</repository>


由於spring3.1.1基於servlet3.0,因此需要將原先2.5的介面進行版本指定:


<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>


spring3.1.1為了支援hibernate4,相關部分做了很大改動,除了一步步排錯,別無他法,而且這些錯誤會因專案不同而異,即case by case根據專案實情來改。這裡將常見的幾個錯誤以及解決辦法羅列如下:

[b][color=red]錯誤1:java.lang.NoClassDefFoundError: org/hibernate/cache/CacheProvider[/color][/b]
原因:spring的sessionfactory和transactionmanager與支援hibernate3時不同。
解決:

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
...
</bean>


<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>

[b]
[color=red]錯誤2:java.lang.NoSuchMethodError: [/color][/b]org.hibernate.SessionFactory.openSession()Lorg/hibernate/classic/Session
原因:hibernate4之後,spring31把HibernateDaoSupport去除,包括資料訪問都不需要hibernatetemplate,這意味著dao需要改寫,直接使用hibernate的session和query介面。
解決:為了改寫dao,足足花了一天時間,然後一個個介面進行單元測試,這是蛋疼的一個主要原因。

[b][color=red]錯誤3:nested exception is org.hibernate.HibernateException: No Session found for current thread[/color][/b]
原因:發現一些bean無法獲得當前session,需要把之前一些方法的事務從NOT_SUPPORT提升到required,readonly=true
見https://jira.springsource.org/browse/SPR-9020
http://www.iteye.com/topic/1120924
解決:

<tx:advice id="baseServiceAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" propagation="REQUIRED"/><!--之前是NOT_SUPPORT-->
<tx:method name="find*" read-only="true" propagation="REQUIRED"/><!--之前是NOT_SUPPORT-->
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="remove*" propagation="REQUIRED"/>
<tx:method name="add*" propagation="REQUIRED"/>
<!--預設其他方法都是REQUIRED-->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>


[b][color=red]錯誤4:與錯誤3報錯類似,java.lang.NoSuchMethodError:[/color][/b] org.hibernate.SessionFactory.openSession()Lorg/hibe
rnate/classic/Session;
at org.springframework.orm.hibernate3.SessionFactoryUtils.doGetSession(S
essionFactoryUtils.java:324) [spring-orm-3.1.1.RELEASE.jar:3.1.1.RELEASE]
at org.springframework.orm.hibernate3.SessionFactoryUtils.getSession(Ses
sionFactoryUtils.java:202) [spring-orm-3.1.1.RELEASE.jar:3.1.1.RELEASE]
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter

原因:因為opensessioninview filter的問題,如果你的配置還是hibernate3,需要改為hibernate4

<filter>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>


以上這些錯誤僅僅是將原有程式碼部署發現的,當然,隨著繼續深入,可能會有更多問題暴露出來,包括程式碼需要調整,新feature要使用,任重而道遠。

相關文章