2009-07-30 5 views
4

Je suis nouveau au printemps, alors j'ai mis Spring 3.0M3 sur un serveur Tomcat sur mon Mac, fait un projet Eclipse, terminé un Hello World et j'ai voulu faire un l'objet persiste avec Hibernate. J'ai créé une table User sur mon serveur MySQL, créé un objet User avec tous les getters et setters (j'aurais vraiment aimé que Java prenne ici une file d'Objective-C et ajoute des propriétés dynamiques.) Trop de code avec du code de propriété généré) , fait un objet UserDao pour rechercher et enregistrer un utilisateur, et fait la configuration du bean. Ça se passe plutôt bien ... sauf que la session n'est pas initialisée. Pourquoi est-ce? Je peux accéder à la base de données très bien à partir de cet ordinateur en utilisant ces informations d'identification.Hibernate/Spring3: impossible d'initialiser le proxy - pas de session

Je me rends compte que c'est probablement juste des choses normales pour les débutants, mais tout ce que j'ai trouvé sur l'erreur lors du googling, ce sont les gens qui perdent les sessions à mi-chemin entre Hibernate 2 et 3. Je ne change pas , et autant que je peux dire que la session n'est jamais faite.

Voici mon erreur:

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) 

Voici ma config de servlet pour les haricots liés:

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

Voici ma classe User:

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

Et voici mon 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; 
    } 
} 

Voici mon interface UserService

public interface UserService { 

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

et sa mise en œuvre:

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

Et enfin, voici mon 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; 
    } 

} 

J'espère que vous avez quelques bons conseils que je peux utiliser: -) S'il y a quelque chose d'autre dans le code, vous sentez que je fais le mauvais chemin/non-printemps, j'aimerais entendre parler de t chapeau aussi bien.

Vive

Nik 
+0

voir la mise à jour – skaffman

Répondre

8

Votre trace de la pile ne correspond pas avec l'exemple de code que vous avez posté pour UserDao. La trace indique que vous appelez HibernateTemplate.initialize() de UserDao.lookupUser(), mais votre code d'exemple ne fait rien de tel (de même il ne devrait pas, initialize() ne devrait pas être appelé ici). Edit: OK, avec la nouvelle trace de la pile, il semble que le problème est simplement que vous appelez hibernateTemplate.load(), qui ne devrait être utilisé que dans des circonstances spécifiques (et ce n'est pas l'un d'entre eux). Vous devriez appeler au hibernateTemplate.get(). Lorsque vous faites l'appel dao, vous "chargez" l'objet.

+0

Oups, j'ai essayé de nettoyer un peu tout en écrivant la question. Laissez-moi le planter à nouveau et mettre à jour le stacktrace :-) – niklassaers

+0

Stacktrace mis à jour :-) – niklassaers

+0

Aha !!! Merci beaucoup!!!! Le livre (très excelent que j'ai à ajouter), Spring in Actino à la page 190 dit explicitement .load(), donc j'ai utilisé ça. Peut-être que cela a été changé depuis que le livre a été écrit. Que signifie .load() maintenant/en quoi est-il différent de .get()? Maintenant tout fonctionne super. Merci TRÈS TRÈS beaucoup :-) – niklassaers

3

Le chargement ne frappe pas la base de données, il retournera un proxy sur l'objet de sorte que la base de données ne soit frappée que lorsque c'est absolument nécessaire.

Vous n'avez pas commencé une transaction avant le chargement - le chargement fonctionne parce que vous avez activé les lectures non-transactionnelles (il est activé par défaut). Il ne dit pas, désolé, aucune transaction (il en crée une pour que vous puissiez lire, ce qui se termine immédiatement).

Ainsi quand vous faites le getName quand il doit effectivement frapper la base de données il vous indique "aucune session" parce que la session qui a chargé cet objet est fermée (elle a été fermée immédiatement). Ce que vous devez faire pour le réparer est de commencer la transaction au début de l'appel de servlet et de le terminer à la fin - de cette façon quand vous faites le getName, la session sera toujours disponible.

Il y a probablement quelque chose au printemps qui va gérer cette plomberie pour vous.

+0

Donc, ce que vous dites est que je ne peux pas utiliser un flux non-transactionnel? Deuxièmement, j'avais l'impression que Spring s'occuperait de ça pour moi. Après tout, il a la source de données, la sessionFactory et l'entité? Troisièmement, j'ai désactivé la récupération paresseuse, donc il ne faut pas simplement créer l'objet proxy, il devrait aussi le peupler, non? – niklassaers

+0

Maintenant, j'ai mis à jour ma question pour inclure un service qui peut être utilisé dans une transaction et inclus un gestionnaire de transaction. Cependant, j'ai toujours la même erreur: pas de session. Comment puis-je lancer cette session? Le mettre dans une transaction n'a pas semblé aider – niklassaers

Questions connexes