Spring 4.1.5.RELEASE Hibernate 4.3的SessionFactory依赖注入失败8.Final

Spring 4.1.5.RELEASE fails to do dependency injection for SessionFactory of Hibernate 4.3.8.Final

问题不重复,因为涉及 Hibernate

James的回答部分解决了问题,我采纳了,新开一个问题,请跟进

我正在尝试将 SessionFactory 注入存储库 class;但是,它看起来不像代码 returns NullPointer 异常那样工作。 我清理并重建了项目,但问题仍然存在。我还将 @Autowired 放在 setSessionFactory 方法上,但没有帮助。

界面

public interface TestRep {
public void get(int id);
}

Class

@Repository
public class TestRepImpl implements TestRep{

    @Autowired
    SessionFactory sessionFactory;


    public TestRepImpl() {

    }

    public TestRepImpl(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

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

    @Transactional
    public void get(int id) {
        String hql = "from Business where id=" + id;
        Query query = sessionFactory.getCurrentSession().createQuery(hql);
         ....

pr-servlet.xml

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

<context:annotation-config/>
 .....
<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation" value="classpath:hibernate.cfg.xml" />
</bean>

<tx:annotation-driven />
<bean id="transactionManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="TestRep" class="com.project.repository.TestRepImpl">
    <constructor-arg>
        <ref bean="sessionFactory" />
    </constructor-arg>
</bean>

StackTrace

    Mar 10, 2015 12:22:21 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [pr] in context with path [/project] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException
    at com.project.repository.TestRepImpl.get(TestRepImpl.java:39)
    at com.project.web.MainController.index(MainController.java:17)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:777)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:706)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1074)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)

罐子

主控制器

@Controller
public class MainController {

     @RequestMapping("/{viewName}.htm")
     public String index(@PathVariable(value = "viewName") String viewName) {
     System.err.println(viewName);
     Test test = new Test();
     test.get(1);
     if (isValidView(viewName)) {
     return viewName;
     }
     return null;
     }

    @RequestMapping("/{viewName}/{viewName2}") //suburb/catname
    public String index(@PathVariable(value = "viewName") String viewName, Model model) {
        System.err.println(viewName);
        if (isValidView(viewName)) {
            model.addAttribute("viewName",viewName);
            return "page";
        }
        return null;
    }

    private boolean isValidView(String viewName) {
        switch (viewName) {
        case "index":
        case "aboutus":
            return true;
        }
        return false;
    }

}

测试

@Service 
public class Test {

    public void get(int i){
         TestRepImpl test = new TestRepImpl();
         test.get(i);
    }
}

Hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">12</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>

        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">update</property>


        <mapping class="com.myproject.model.MyTable" />
        ....

您需要在任何地方都使用自动装配,否则您的程序将无法运行。 Spring 只能自动装配存在于 Spring 应用程序上下文中的 bean,这是您的 @Controller@Service@Repository 注释应该做的。但是,如果您的配置 XML.

中没有 <context:component-scan base-package="your.base.package"> 标记,这些注释将毫无意义

因此,假设您的控制器、服务和 DAO 都在包 com.repository 中的某处,您需要将此行添加到您的 XML 配置中。

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

它的作用是告诉 Spring 在 foo.bar.baz 包(和所有子包)中递归搜索带有 @Controller 注释的 classes,@Service@Repository@Component,实例化它们的单例实例并使它们有资格自动连接到其他 classes。

您还需要修改控制器和服务 classes 才能使用 @Autowired。如果您使用 new 关键字实例化它们,Spring 将无法管理您的 classes。这些 bean 是单例的(您的程序中应该只存在一个实例)是有原因的。

您的控制器需要进行如下更改。

@Controller
public class MainController {

    @Autowired
    private TestService testService;

    @RequestMapping("/{viewName}.htm")
    public String index(@PathVariable(value = "viewName") String viewName) {
         System.err.println(viewName);
         testService.get(1);
         if (isValidView(viewName)) {
             return viewName;
         }
         return null;
     }

    @RequestMapping("/{viewName}/{viewName2}") //suburb/catname
    public String index(@PathVariable(value = "viewName") String viewName, Model model) {
        System.err.println(viewName);
        if (isValidView(viewName)) {
            model.addAttribute("viewName",viewName);
            return "page";
        }
        return null;
    }

    private boolean isValidView(String viewName) {
        switch (viewName) {
        case "index":
        case "aboutus":
            return true;
        }
        return false;
    }
}

请注意,您将服务 class 自动连接到控制器中。

您的服务class需要实现一个接口。 Spring 使用接口完成所有这些自动装配魔术。您不能自动装配未实现接口的 class,除非您在 XML 配置中专门创建了 class 的实例。

您的服务 class 需要更改如下:

@Service 
public class TestServiceImpl implements TestService {
    @Autowired
    private TestRepDao testDao;

    @Transactional
    public void get(int i){
         testDao.get(i);
    }
}

并创建一个名为 TestService 的接口。

public interface TestService{
    public void get(int i);
}

然后你的 DAO 变成了

@Repository
public class TestRepDaoImpl implements TestRepDao{

    @Autowired
    private SessionFactory sessionFactory;

    public void get(int id) {
        String hql = "from Business where id=" + id;
        Query query = sessionFactory.getCurrentSession().createQuery(hql);
    }
}

它实现了接口 TestRepDao:

public interface TestRepDao{
    public void get(int id);
}

你也可以去掉

的声明
<bean id="TestRep" class="com.project.repository.TestRepImpl">
    <constructor-arg>
        <ref bean="sessionFactory" />
    </constructor-arg>
</bean>

来自您的 XML 配置。

如您所见,我更改了一些 class 名称以更好地适应 Spring 约定。您的应用程序应该从 Controller 向下分层到 Service Class 再到 DAO,然后再次退出。如果您按照我在此处列出的步骤进行操作,这应该会起作用。

需要记住的几点:

  1. Spring 讨厌 new 关键字。如果您发现自己在使用它,那么您可能做错了什么。
  2. Spring 在整个应用程序中通过组件扫描拾取的任何 classes 中只有一个实例。不要使用这些 classes 来存储持久数据或状态。这条路充满了线程问题、竞争条件和充满酸蜘蛛的坑。
  3. 阅读并重新阅读文档,如果您以前从未使用过 Spring,那么这些概念很难掌握。 Spring 非常易于使用,只要您了解它的工作原理以及它希望您如何使用它。
  4. Spring 适用于接口。如果您的 class 没有实现接口,那么 Spring 不能在不使用 AspectJ Load Time Weaving 的情况下代理它,这是另一天的对话,而不是您应该使用的东西,只是开始.如果您不知道为什么 Spring 需要创建您的对象的代理,则需要重新阅读文档,直到您了解应用程序上下文。
  5. 我将 @Transactional 注释移到了服务 class 中。这是因为 DAO 应该只关心从数据库访问和检索数据,而不需要管理 connection/session 到数据库,这是服务 class.[=74= 的工作]
  6. 我猜你在遇到异常后开始使用 new 关键字,说出类似于

    的内容

    No qualifying bean of type found for dependency TestService.

    这是 Spring 告诉您它没有可以自动连接到任何 class 上的 TestService 字段的 bean。当Spring告诉你事情的时候听听,它会让你省去很多麻烦。

  7. 不要气馁,当我尝试学习如何使用 Spring 时,我遇到了所有这些问题,但我克服了它,现在 Spring 是我的第二天性。