Spring MVC3.2.2 + Hibernate4 + @Autowire SessionFa

2019-08-30 17:57发布

I am using GenricHibernateDAO which autowires a sessionfactory, which getting set to null all the time when I call the save(user) method through controller, it give me a null pointer exception.

package com.hdo.dao;
    public class GenericHibernateDAO<T> implements GenericDAO<T> {

        @Autowired
        private SessionFactory sessionFactory;

        public void setSessionFactory(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
        }


        @Override
        @Transactional
        public void save(T t) {
            // TODO Auto-generated method stub
            sessionFactory.getCurrentSession().save(t);
        }
    }

UserDAO :

@Repository
public class UserDAO extends GenericHibernateDAO<User> {

    public UserDAO() {
        super(User.class);
    }
    public void createUser(User user) {

        save(user);
    }
}

Controller :

@Controller
public class BasicController {

    Logger _LOG = Logger.getLogger(BasicController.class);

    @RequestMapping("/")
    public ModelAndView home() {
        return new ModelAndView("index");
    }

    @RequestMapping("/userHome")
    public ModelAndView goHome(@ModelAttribute("user") User user, Map<String, Object> map, HttpServletRequest request) {
        if (null != user) {
            //userForm.get
            int noOfBreeds = Integer.parseInt(user.getNoOfBreeds());
            for (int i = 0; i < noOfBreeds; i++) {
                Pet pet = new Pet();
                String dogName = request.getParameter("dogName"+i);
                String breed = request.getParameter("breed"+i);
                pet.setPetName(dogName);
                pet.setPetType(breed);

                user.addPet(pet);
            }

            new UserDAO().save(user);
        }

        return new ModelAndView("userHome");
    }
}

pom.xml (properties)

spring.version : 3.2.2.RELEASE
jdk.version : 1.7
hibernate.version : 4.2.0.Final
mysql.connector.version : 5.1.21 
tomcat.version : 7.0.33
cglib : 2.2.2
jstl : 1.2
commons-dbcp : 1.4
javax.servlet : 3.0.1

spring-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"

       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">        

    <context:component-scan base-package="com.hdo" />
    <mvc:annotation-driven />

    <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="classpath:i18n/messages" />
        <property name="defaultEncoding" value="UTF-8" />
    </bean>

    <bean id="localeChangeInterceptor"
        class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
        <property name="paramName" value="lang" />
    </bean>

    <bean id="localeResolver"
        class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
        <property name="defaultLocale" value="en" />
    </bean>

    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>

</beans>

application-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"

       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

    <context:annotation-config></context:annotation-config>
<context:property-placeholder location="classpath:jdbc.properties"/>

<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName">
        <value>${jdbc.driverClassName}</value>
    </property>
    <property name="url">
        <value>${jdbc.databaseurl}</value>
    </property>
    <property name="username">
        <value>${jdbc.username}</value>
    </property>
    <property name="password">
        <value>${jdbc.password}</value>
    </property>
</bean>

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="com.hdo.model" /> <!-- assuming that is the package with your hibernate entities -->
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${jdbc.dialect}</prop>
                <prop key="hibernate.show_sql">${jdbc.showSql}</prop>
            </props>
        </property>
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"/>

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

</beans>

Web.xml :

    <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/application-context.xml, /WEB-INF/spring-servlet.xml</param-value>
 </context-param>

<listener>
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value></param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

Logs are here :

    00:06:06,297 DEBUG DefaultIdentifierGeneratorFactory:93 - Registering IdentifierGenerator strategy [enhanced-table] -> [org.hibernate.id.enhanced.TableGenerator]
    00:06:06,304  INFO Configuration:1969 - HHH000044: Configuring from URL: file:/home/hanu/tools/tomcat7maven_hpo/webapps/hpo/WEB-INF/classes/hibernate.cfg.xml
    00:06:06,357 DEBUG DTDEntityResolver:68 - Trying to resolve system-id [http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd]
    00:06:06,365 DEBUG DTDEntityResolver:70 - Recognized hibernate namespace; attempting to resolve on classpath under org/hibernate/
    00:06:06,367 DEBUG DTDEntityResolver:107 - Located [http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd] in classpath
    00:06:06,400 DEBUG Configuration:2134 - Session-factory config [null] named class [com.hdo.model.User] for mapping
    00:06:06,417  INFO Configuration:2074 - HHH000041: Configured SessionFactory: null


    00:06:06,715 DEBUG SimpleValueBinder:331 - building SimpleValue for userName
    00:06:06,716 DEBUG PropertyBinder:260 - Building property userName
    00:06:06,719 DEBUG SimpleValueBinder:369 - Setting SimpleValue typeName for id
    00:06:06,720 DEBUG SimpleValueBinder:369 - Setting SimpleValue typeName for confirmPassword
    00:06:06,720 DEBUG SimpleValueBinder:369 - Setting SimpleValue typeName for country
    00:06:06,720 DEBUG SimpleValueBinder:369 - Setting SimpleValue typeName for email
    00:06:06,721 DEBUG SimpleValueBinder:369 - Setting SimpleValue typeName for location
    00:06:06,721 DEBUG SimpleValueBinder:369 - Setting SimpleValue typeName for noOfBreeds
    00:06:06,722 DEBUG SimpleValueBinder:369 - Setting SimpleValue typeName for password
    00:06:06,722 DEBUG SimpleValueBinder:369 - Setting SimpleValue typeName for postCode
    00:06:06,723 DEBUG SimpleValueBinder:369 - Setting SimpleValue typeName for state
    00:06:06,723 DEBUG SimpleValueBinder:369 - Setting SimpleValue typeName for userName
    00:06:06,725 DEBUG Configuration:1406 - Processing fk mappings (*ToOne and JoinedSubclass)
    00:06:06,728 DEBUG Configuration:1585 - Processing extends queue
    00:06:06,729 DEBUG Configuration:1643 - Processing extends queue
    00:06:06,729 DEBUG Configuration:1588 - Processing collection mappings
    00:06:06,730 DEBUG Configuration:1598 - Processing native query and ResultSetMapping mappings
    00:06:06,730 DEBUG Configuration:1606 - Processing association property references
    00:06:06,730 DEBUG Configuration:1628 - Creating tables' unique integer identifiers
    00:06:06,731 DEBUG Configuration:1629 - Processing foreign key constraints
    00:06:07,128 DEBUG JdbcServicesImpl:121 - Database ->
       name : MySQL
    version : 5.5.29-0ubuntu0.12.10.1
      major : 5
      minor : 5
    00:06:07,129 DEBUG JdbcServicesImpl:127 - Driver ->
       name : MySQL-AB JDBC Driver
    version : mysql-connector-java-5.1.21 ( Revision: ${bzr.revision-id} )
      major : 5
      minor : 1
    00:06:07,130 DEBUG JdbcServicesImpl:133 - JDBC version : 4.0
    00:06:07,169  INFO Dialect:128 - HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
    00:06:07,216 DEBUG SettingsFactory:114 - Automatic flush during beforeCompletion(): disabled
    00:06:07,217 DEBUG SettingsFactory:120 - Automatic session close at end of transaction: disabled
    00:06:07,217 DEBUG SettingsFactory:131 - JDBC batch size: 15
    00:06:07,218 DEBUG SettingsFactory:137 - JDBC batch updates for versioned data: disabled
    00:06:07,218 DEBUG SettingsFactory:147 - Scrollable result sets: enabled
    00:06:07,219 DEBUG SettingsFactory:153 - Wrap result sets: disabled
    00:06:07,219 DEBUG SettingsFactory:159 - JDBC3 getGeneratedKeys(): enabled
    00:06:07,219 DEBUG SettingsFactory:171 - multi-tenancy strategy : NONE
    00:06:07,220 DEBUG SettingsFactory:177 - Connection release mode: auto
    00:06:07,220  INFO TransactionFactoryInitiator:68 - HHH000399: Using default transaction strategy (direct JDBC transactions)
    00:06:07,226 DEBUG SettingsFactory:199 - Using BatchFetchStyle : LEGACY
    00:06:07,227 DEBUG SettingsFactory:218 - Maximum outer join fetch depth: 2
    00:06:07,227 DEBUG SettingsFactory:224 - Default batch fetch size: 1
    00:06:07,228 DEBUG SettingsFactory:230 - Generate SQL with comments: disabled
    00:06:07,228 DEBUG SettingsFactory:236 - Order SQL updates by primary key: disabled
    00:06:07,228 DEBUG SettingsFactory:242 - Order SQL inserts for batching: disabled
    00:06:07,229 DEBUG SettingsFactory:250 - Default null ordering: none
    00:06:07,230 DEBUG SettingsFactory:541 - Query translator: org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory
    00:06:07,234  INFO ASTQueryTranslatorFactory:48 - HHH000397: Using ASTQueryTranslatorFactory
    00:06:07,235 DEBUG SettingsFactory:260 - Query language substitutions: {}
    00:06:07,235 DEBUG SettingsFactory:266 - JPA-QL strict compliance: disabled
    00:06:07,236 DEBUG SettingsFactory:274 - Second-level cache: enabled
    00:06:07,236 DEBUG SettingsFactory:280 - Query cache: disabled


    00:06:07,842 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping': no URL paths identified
    00:06:07,843 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter': no URL paths identified
    00:06:07,843 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter': no URL paths identified
    00:06:07,843 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0': no URL paths identified
    00:06:07,843 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'messageSource': no URL paths identified
    00:06:07,843 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'localeChangeInterceptor': no URL paths identified
    00:06:07,844 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'localeResolver': no URL paths identified
    00:06:07,844 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'org.springframework.web.servlet.view.InternalResourceViewResolver#0': no URL paths identified
    00:06:07,844 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'dataSource': no URL paths identified
    00:06:07,844 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'sessionFactory': no URL paths identified
    00:06:07,845 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'genericHibernateDAO': no URL paths identified
    00:06:07,845 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor': no URL paths identified
    00:06:07,845 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'environment': no URL paths identified
    00:06:07,845 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'systemProperties': no URL paths identified
    00:06:07,846 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'systemEnvironment': no URL paths identified
    00:06:07,846 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'servletConfig': no URL paths identified
    00:06:07,846 DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry': no URL 

    00:06:07,886 DEBUG DefaultListableBeanFactory:215 - Creating shared instance of singleton bean 'org.springframework.web.servlet.view.InternalResourceViewResolver#0'
    00:06:07,886 DEBUG DefaultListableBeanFactory:435 - Creating instance of bean 'org.springframework.web.servlet.view.InternalResourceViewResolver#0'
    00:06:07,902 DEBUG DefaultListableBeanFactory:509 - Eagerly caching bean 'org.springframework.web.servlet.view.InternalResourceViewResolver#0' to allow for resolving potential circular references
    00:06:07,926 DEBUG DefaultListableBeanFactory:463 - Finished creating instance of bean 'org.springframework.web.servlet.view.InternalResourceViewResolver#0'
    00:06:07,927 DEBUG DefaultListableBeanFactory:246 - Returning cached instance of singleton bean 'dataSource'
    00:06:07,927 DEBUG DefaultListableBeanFactory:246 - Returning cached instance of singleton bean 'sessionFactory'
    00:06:07,927 DEBUG DefaultListableBeanFactory:215 - Creating shared instance of singleton bean 'genericHibernateDAO'
    00:06:07,928 DEBUG DefaultListableBeanFactory:435 - Creating instance of bean 'genericHibernateDAO'
    00:06:07,930 DEBUG InjectionMetadata:71 - Registered injected element on class [com.hdo.dao.GenericHibernateDAO]: AutowiredFieldElement for private org.hibernate.SessionFactory com.hdo.dao.GenericHibernateDAO.sessionFactory
    00:06:07,931 DEBUG DefaultListableBeanFactory:509 - Eagerly caching bean 'genericHibernateDAO' to allow for resolving potential circular references
    00:06:07,935 DEBUG InjectionMetadata:85 - Processing injected method of bean 'genericHibernateDAO': AutowiredFieldElement for private org.hibernate.SessionFactory com.hdo.dao.GenericHibernateDAO.sessionFactory
    00:06:07,935 DEBUG DefaultListableBeanFactory:246 - Returning cached instance of singleton bean 'sessionFactory'
    00:06:07,936 DEBUG AutowiredAnnotationBeanPostProcessor:433 - Autowiring by type from bean name 'genericHibernateDAO' to bean named 'sessionFactory'
    00:06:07,936 DEBUG DefaultListableBeanFactory:246 - Returning cached instance of singleton bean 'sessionFactory'
    00:06:07,937 DEBUG DefaultListableBeanFactory:463 - Finished creating instance of bean 'genericHibernateDAO'
    00:06:07,937 DEBUG DefaultListableBeanFactory:246 - Returning cached instance of singleton bean 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor'
    00:06:07,937 DEBUG XmlWebApplicationContext:858 - Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor@2f3fc03c]
    00:06:07,938 DEBUG DefaultListableBeanFactory:246 - Returning cached instance of singleton bean 'lifecycleProcessor'


    00:36:51,774 DEBUG DispatcherServlet:823 - DispatcherServlet with name 'spring' processing POST request for [/hpo/userHome.do]
11:00:56,266 DEBUG ResponseStatusExceptionResolver:132 - Resolving exception from handler [public org.springframework.web.servlet.ModelAndView com.hdo.spring.controller.BasicController.goHome(com.hdo.model.User,java.util.Map<java.lang.String, java.lang.Object>,javax.servlet.http.HttpServletRequest)]: java.lang.NullPointerException
11:00:56,267 DEBUG DefaultHandlerExceptionResolver:132 - Resolving exception from handler [public org.springframework.web.servlet.ModelAndView com.hdo.spring.controller.BasicController.goHome(com.hdo.model.User,java.util.Map<java.lang.String, java.lang.Object>,javax.servlet.http.HttpServletRequest)]: java.lang.NullPointerException
11:00:56,269 DEBUG DispatcherServlet:959 - Could not complete request
java.lang.NullPointerException
    at com.hdo.dao.GenericHibernateDAO.getCurrentSession(GenericHibernateDAO.java:27)
    at com.hdo.dao.GenericHibernateDAO.save(GenericHibernateDAO.java:33)
    at com.hdo.spring.controller.BasicController.goHome(BasicController.java:59)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)

I am totally new to spring mvc I guess I am dealing with multiple problems here, i get sessionFactory set to [null] and Rejected bean name 'sessionFactory'. I have tried using all latest jars in spring mvc3.2.2 and hibernate4. I couldnt figure out whats the issue, so please help ?

1条回答
Juvenile、少年°
2楼-- · 2019-08-30 18:34

Judging on your LocalSessionFactoryBean you have probably mixed some tutorials for Hibernate 3 and 4 (they are configured in slightly different way).

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.hdo.model" /> <!-- assuming that is the package with your hibernate entities -->
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${jdbc.dialect}</prop>
            <prop key="hibernate.show_sql">${jdbc.showSql}</prop>
        </props>
    </property>
</bean>

I am also missing transaction management configuration:

<tx:annotation-driven />

Another mistake is defining DAO bean manually if it is being already picked by component-scan:

<context:component-scan base-package="com.hdo.dao" />

And last - this kind of configuration is usually placed inside root web application context. Servlet application context is for handlers (controllers), handler mappings, handler adapters and handler interceptors (like the LocaleChangeInterceptor).


UPDATE There are several errors in your updated code. Lets go through them one by one:

  • ERROR 1: You are loading servlet app context by root web app context in your web.xml.
  • SOLUTION 1: Remove spring-servlet.xml from the context-param and delete the empty init-param for the spring servlet (spring-servlet.xml is the default name it will load).
  • ERROR 2: Your component scan in the servlet app context is too wide. It will load also beans belonging to root web app context.
  • SOLUTION 2: Change component scan inside servlet app context to <context:component-scan base-package="com.hdo.controller" /> and add a different one to the root app context <context:component-scan base-package="com.hdo.dao" /> (you can also remove annotation-config declaration as that comes automatically with component scan).
  • ERROR 3: Your transaction configuration for the DAO will not work as you are calling non-annotated method, which in turn is calling the save method directly. This will not work as the second direct call will not go through TX AOP proxy.
  • SOLUTION 3: Delete your createUser method in UserDAO and call save method directly from the controller.
  • ERROR 4: You are creating UserDAO bean manually. When using IoC container such as Spring, you need to let it inject your dependencies.
  • SOLUTION 4: In your controller delete the new UserDAO line and add @Autowire UserDAO userDao; property. Spring will inject your DAO instance for you. Such instance will have its dependencies (such as sessionFactory) initialized.
  • ERROR 5: You probably don't understand what you are doing.
  • SOLUTION 5: It is very hard to help you if you lack basic Java and Spring knowledge. Your question about a single problem become step-by-step tutorial help service. Please invest a little bit more time in learning the basic principles. Spring reference manuals are a good start. I know they are lengthy and you might not understand 100% (I know I don't ;)), but it is well spent time reading them.
查看更多
登录 后发表回答