2009-07-30 82 views
4

我是Spring的新手,所以我把Spring 3.0M3放在我的Mac上的Tomcat服務器上,做了一個Eclipse項目,完成了一個Hello World,然後想做一個對象持久與Hibernate。我在我的MySQL服務器上創建了一個用戶表,使用所有的getter和setter創建了一個User對象(我真的希望Java在這裏從Objective-C中取出一個隊列並添加動態屬性,生成的屬性代碼會造成太多的代碼混亂) ,創建一個UserDao對象來查找並保存一個用戶,並創建了bean配置。它相當好......除了會話未初始化。爲什麼是這樣?我可以使用這些憑據從這臺計算機上很好地訪問數據庫。Hibernate/Spring3:無法初始化代理 - 沒有會話

我意識到這可能只是普通的初學者的東西,但我發現的所有錯誤,而谷歌搜索一直是在從Hibernate 2轉換到3時中途丟失會話的人。我沒有過渡,並且據我所知,這個會議從來沒有完成。

這裏是我的錯誤:

SEVERE: Servlet.service() for servlet HelloApp threw exception 
org.hibernate.LazyInitializationException: could not initialize proxy - no Session 
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:57) 
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:111) 
    at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:150) 
    at com.saers.data.entities.User$$EnhancerByCGLIB$$c2f16afd.getName(<generated>) 
    at com.saers.view.web.controller.HelloWorldController.handleRequestInternal(HelloWorldController.java:22) 
    at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153) 
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:763) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:709) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:613) 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:525) 
    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:293) 
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849) 
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583) 
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454) 
    at java.lang.Thread.run(Thread.java:637) 

這裏是我的相關Bean servlet配置:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
    <property name="url"  value="jdbc:mysql://10.0.0.3:3306/HelloDB" /> 
    <property name="username" value="hello" /> 
    <property name="password" value="w0rld" /> 
    <property name="initialSize" value="2" /> 
    <property name="maxActive" value="5" /> 
    </bean> 

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource"/> 
    <property name="annotatedClasses"> 
     <list> 
     <value>com.saers.data.entities.User</value> 
     </list> 
    </property> 
    <property name="hibernateProperties"> 
     <props> 
     <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
     <prop key="hibernate.show_sql">true</prop> 
     <prop key="hibernate.lazy">false</prop> 
     </props> 
    </property> 
    </bean> 

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

    <bean id="userDAO" class="com.saers.data.dao.UserDao"> 
    <property name="sessionFactory" ref="sessionFactory"/> 
    </bean> 

    <bean id="txProxyTemplate" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> 
    <property name="transactionManager" ref="transactionManager"/> 
    <property name="transactionAttributes"> 
     <props> 
     <prop key="add*">PROPAGATION_REQUIRED</prop> 
     <prop key="update*">PROPAGATION_REQUIRED</prop> 
     <prop key="delete*">PROPAGATION_REQUIRED</prop> 
     <prop key="*">PROPAGATION_SUPPORTS,readOnly</prop> 
     </props> 
    </property> 
    </bean> 

    <bean id="userService" parent="txProxyTemplate"> 
    <property name="target"> 
     <bean class="com.saers.business.UserServiceImpl"> 
     <property name="userDao" ref="userDAO"/> 
     </bean> 
    </property> 
    <property name="proxyInterfaces" value="com.saers.business.UserService"/> 
    </bean> 

    <bean name="/" class="com.saers.view.web.controller.HelloWorldController"> 
    <property name="userService" ref="userService"/> 
    </bean> 

這裏是我的用戶等級:

package com.saers.data.entities; 

import java.util.Date; 
import java.io.Serializable; 

import javax.persistence.*; 

@Entity 
@Table(name = "User") 
public class User implements Serializable { 

    private static final long serialVersionUID = -6123654414341191669L; 

    @Id 
    @Column(name = "WebUserId") 
    private String WebUserId; 

    @Column(name = "Name") 
    private String Name; 
    /** 
    * @return the webUserId 
    */ 
    public synchronized String getWebUserId() { 
     return WebUserId; 
    } 
    /** 
    * @param webUserId the webUserId to set 
    */ 
    public synchronized void setWebUserId(String webUserId) { 
     WebUserId = webUserId; 
    } 
    /** 
    * @return the name 
    */ 
    public synchronized String getName() { 
     return Name; 
    } 
    /** 
    * @param name the name to set 
    */ 
    public synchronized void setName(String name) { 
     Name = name; 
    } 
} 

這裏是我的UserDAO :

package com.saers.data.dao; 

import java.util.List; 

import com.saers.data.entities.User; 

import org.springframework.orm.hibernate3.support.*; 


public class UserDao extends HibernateDaoSupport { 

    public void saveUser(User user) { 
     getHibernateTemplate().saveOrUpdate(user); 
    } 

    public User lookupUser(String WebUserId) { 
     User user = getHibernateTemplate().load(User.class, WebUserId); 
     return user; 
     return user; 
    } 
} 

這裏是我的UserService接口

public interface UserService { 

    public User lookupUser(String webUserId); 
    public void setUserDao(UserDao userDao); 
} 

及其實施:

public class UserServiceImpl implements UserService { 

    private UserDao userDao; 
    public void setUserDao(UserDao userDao) { 
     this.userDao = userDao; 
    } 

    @Override 
    public User lookupUser(String webUserId) { 

     return userDao.lookupUser(webUserId); 
    } 
} 

最後,這裏是我的HelloWorldController:

package com.saers.view.web.controller; 

import com.saers.data.entities.User; 
import com.saers.business.UserService; 

import org.springframework.web.servlet.mvc.*; 
import org.springframework.web.servlet.*; 
import javax.servlet.http.*; 
import org.apache.commons.logging.*; 



public class HelloWorldController extends AbstractController { 

    protected final Log logger = LogFactory.getLog(getClass()); 

    @Override 
    public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { 

    logger.info("Get bean"); 
    User user = userService.lookupUser("helloUser"); 
    logger.info("Found out that this user was last changed " + user.getName()); 
    logger.info("Return View"); 
    ModelAndView mv = new ModelAndView("HelloWorld.jsp", "user", user); 
    return mv; 
    } 

    private UserService userService = null; 
    public void setUserService(UserService userService) { 
     this.userService = userService; 
    } 

} 

我希望你有一些好的建議,我可以使用: - )如果代碼中還有其他東西,你會覺得我做錯了/非春天的方式,我很想聽聽帽子也是如此。

乾杯

Nik 
+0

查看更新的答案 – skaffman 2009-07-30 14:01:29

回答

8

您的堆棧跟蹤不跟你張貼UserDao示例代碼相匹配。跟蹤表明你打電話給HibernateTemplate.initialize()UserDao.lookupUser(),但你的示例代碼沒有這樣的事情(以及它不應該,initialize()不應該在這裏調用)。

編輯:好的,用新的堆棧跟蹤,看起來問題很簡單,你只需要調用hibernateTemplate.load(),這應該只在特定情況下使用(而這不是其中之一)。您應該打電話給hibernateTemplate.get()

+0

糟糕,我在寫問題時嘗試清理了一下。讓我再次崩潰並更新堆棧跟蹤:-) – niklassaers 2009-07-30 13:55:31

+0

Stacktrace更新:-) – niklassaers 2009-07-30 13:58:50

3

當您進行dao調用時,您會「加載」對象。加載不會觸及數據庫,它會將一個代理返回到該對象上,以便在絕對必要時纔會觸發數據庫。

您在加載之前未啓動事務 - 加載因爲您打開了非事務性讀取(默認情況下處於啓用狀態)而起作用。它沒有說,抱歉,沒有交易(它基本上創造一個讓你做閱讀,立即結束)。

因此,當您實際上必須擊中數據庫時執行getName時,會告訴您「無會話」,因爲已加載該對象的會話已關閉(它立即關閉)。

你需要做什麼來解決它是在servlet調用開始時啓動事務並在結束時結束它 - 這樣,當你執行getName時,會話仍然可用。

在春天可能有東西會處理這個管道給你。

相關問題