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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1206460/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 15:37:03  来源:igfitidea点击:

Hibernate/Spring3: could not initialize proxy - no Session

javahibernatespringexceptionsession

提问by niklassaers

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.

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

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.

我意识到这可能只是普通的初学者的东西,但我在谷歌搜索时发现的所有错误都是在从 Hibernate 2 过渡到 3 时丢失会话的人。我没有过渡,到目前为止正如我所知道的那样,会议从未举行过。

Here's my error:

这是我的错误:

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)

Here is my servlet config for the related beans:

这是我的相关 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>

Here is my User class:

这是我的用户类:

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;
    }
}

And here is my UserDao:

这是我的 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;
    }
}

Here's my UserService interface

这是我的 UserService 界面

public interface UserService {

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

and its implementation:

及其实施:

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);
    }
}

And finally, here's my HelloWorldController:

最后,这是我的 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.

我希望你有一些我可以使用的好技巧 :-) 如果你觉得代码中有任何其他地方我做错了/非弹簧方式,我也很想听听。

Cheers

干杯

Nik

回答by skaffman

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).

您的堆栈跟踪与您发布的示例代码不匹配UserDao。跟踪表明您正在HibernateTemplate.initialize()从调用UserDao.lookupUser(),但您的示例代码没有做这样的事情(也不initialize()应该,也不应该在这里调用)。

Edit: 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().

编辑:好的,使用新的堆栈跟踪,问题似乎只是您正在调用hibernateTemplate.load(),它应该只在特定情况下使用(这不是其中之一)。您可能应该调用hibernateTemplate.get().

回答by Michael Wiles

When you do the dao call, you "load" the object. Load does not hit the database, it will return a proxy onto the object so that the database is only hit when absolutely necessary.

当您执行 dao 调用时,您“加载”了对象。Load 不会命中数据库,它会返回一个代理到对象上,以便数据库仅在绝对必要时才被命中。

You did not start a transaction before the load - the load works because you have non transactional reads turned on (it's on by default). It doesn't say, sorry, no transaction (it basically creates one for you to do the read, which ends immediately).

您没有在加载之前启动事务 - 加载工作是因为您打开了非事务性读取(默认情况下它是打开的)。它没有说,抱歉,没有事务(它基本上创建了一个供您阅读,立即结束)。

Thus when you do the getName when it actually has to hit the database it tells you "no session" because the session which did load that object is closed (it was closed immediately).

因此,当您在实际必须访问数据库时执行 getName 时,它​​会告诉您“没有会话”,因为加载该对象的会话已关闭(它已立即关闭)。

What you need to do to fix it is start the transaction at the beginning of the servlet call and end it at the end - that way when you do the getName the session will still be available.

您需要做的是修复它是在 servlet 调用开始时启动事务并在结束时结束它 - 这样当您执行 getName 时,会话仍然可用。

There's probably something in spring which will handle this plumbing for you.

春天可能有一些东西可以为你处理这个管道。