Hibernate/Spring3:无法初始化代理-没有会话

问题描述:

我是Spring的新手,所以我将Spring 3.0M3放在Mac上的Tomcat服务器上,创建了一个Eclipse项目,完成了Hello World,然后希望使对象与Hibernate保持一致.我已经在MySQL服务器上创建了一个User表,并创建了一个包含所有getter和setter的User对象(我真的希望Java从这里的Objective-C队列中添加动态属性.生成的属性代码太多了,代码杂乱无章) ,制作了一个UserDao对象来查找和保存用户,并进行了Bean配置.进行得很好...除了未初始化会话外.为什么是这样?我可以使用这些凭据从这台计算机访问数据库.

I'm new at Spring, so I put Spring 3.0M3 on a Tomcat server on my Mac, made an Eclipse project, completed a Hello World and then wanted to make an object persist with Hibernate. I've made a User table on my MySQL server, made a User object with all getters and setters (I really wish Java would take a queue from Objective-C here and add dynamic properties. Too much code clutter with generated property-code), made a UserDao object to look up and save a User, and made the bean config. It goes fairly well... except for that the session isn't initialized. Why is this? I can access the database just fine from this computer using those credentials.

我意识到这可能只是普通的初学者,但是我在谷歌搜索时发现的所有错误都是在从Hibernate 2过渡到3时中途丢失会话的人.据我所知,会话从未进行过.

I realize that this is probably just normal beginner stuff, but all I've found on the error while googling has been people that are loosing the sessions mid-way when transitioning from Hibernate 2 to 3. I'm not transitioning, and as far as I can tell the session is never made.

这是我的错误:

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:

Here is my servlet config for the related beans:

<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:

And here is my 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界面

Here's my UserService interface

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:

And finally, here's my 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;
  }

}

我希望您有一些我可以使用的好技巧:-)如果代码中还有其他问题,您会觉得我做错了/非有弹性的方法,那么我也很乐意听到.

I hope you have some good tips I can use :-) If there's anything else in the code you feel that I'm doing the wrong/non-spring way, I would love to hear about that as well.

欢呼

Nik

您的堆栈跟踪与您为UserDao发布的示例代码不匹配.跟踪显示您正在从UserDao.lookupUser()调用HibernateTemplate.initialize(),但是示例代码没有执行任何操作(同样不应该,在这里不应调用initialize()).

Your stack trace does not match up with the sample code you posted for UserDao. The trace says that you're calling HibernateTemplate.initialize() from UserDao.lookupUser(), but your sample code is doing no such thing (as well it shouldn't, initialize() should not be called here).

好的,对于新的堆栈跟踪,看来问题仅在于您正在调用hibernateTemplate.load(),它仅应在特定情况下使用(这不是其中一种).您可能应该呼叫hibernateTemplate.get().

OK, with the new stack trace, it seems the problem is simply that you're calling hibernateTemplate.load(), which should only be used in specific circumstances (and this isn't one of them). You should probably be calling hibernateTemplate.get().