Spring 4.1.5.RELEASE не может выполнить внедрение зависимостей для SessionFactory из Hibernate 4.3.8.Final

Вопрос не повторяется, так как задействован Hibernate

Поскольку ответ Джеймса частично решил проблему, я принял его и открыл новый вопрос, пожалуйста, следите за здесь

Я пытаюсь внедрить SessionFactory в класс репозитория; однако похоже, что это не работает, поскольку код возвращает исключение NullPointer. Я очистил и перестроил проект, но проблема все еще существует. Я также поставил @Autowired в метод setSessionFactory, но это не помогло.

Интерфейс

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

Класс

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

Отслеживание стека

    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" />
        ....

person Jack    schedule 10.03.2015    source источник
comment
Вам не нужен геттер и сеттер для sessionFactory. Кроме того, вы пытались поместить строку ‹tx:annotation-driven/› над объявлением bean-компонента sessionFactory? Просто сравнил мой с вашим.   -  person vphilipnyc    schedule 10.03.2015
comment
Попробуйте удалить свой конструктор. Вам это не нужно, так как вы выполняете автопроводку.   -  person minion    schedule 10.03.2015
comment
@bphilipnyc все та же проблема   -  person Jack    schedule 10.03.2015
comment
@minion все та же проблема   -  person Jack    schedule 10.03.2015
comment
Можете ли вы вставить верхнюю часть pr-servlet.xml? Должно быть что-то вроде: ‹?xml version=1.0 encoding=UTF-8?› ‹beans xmlns=springframework. org/schema/beans xmlns:xsi=w3.org/2001/XMLSchema-instance xmlns:tx=springframework.org/schema/tx xsi:schemaLocation= springframework.org/schema/beans springframework.org/schema/beans/spring-beans-4.1.xsd springframework.org/schema/tx springframework.org/s chema/tx/spring-tx-4.1.xsd  -  person vphilipnyc    schedule 10.03.2015
comment
@bphilipnyc показывает, что контекст не привязан.   -  person Jack    schedule 10.03.2015
comment
Можете ли вы также добавить код MainControlller в сообщение?   -  person RKodakandla    schedule 10.03.2015
comment
У @James-Massey правильный подход - вы можете прочитать о концепциях Spring autowiring (внедрение зависимостей) и посмотреть примеры проектов на github. В Spring есть много придирок к конфигурации, и вы получите исключения, если она хоть немного неверна. Это не займет много времени, если вы немного поиграете с ним. Spring Boot может облегчить некоторые из них. Кроме того, обычно используется JavaConfig вместо XML-конфигурации, основанной на том, что я видел на последней конференции SpringOne. У JavaConfig есть свои плюсы и минусы — просто сообщаю вам об этом.   -  person vphilipnyc    schedule 10.03.2015
comment
@bphilipnyc спасибо за ваш комментарий, из какого источника вы предлагаете его узнать? Я нашел документацию Spring довольно запутанной и неполной. Я ищу учебник с рабочими примерами, я прочитал часть документации, связанную с Hibernate, но мне это не очень помогло.   -  person Jack    schedule 11.03.2015
comment
возможный дубликат Почему мое поле Spring @Autowired равно нулю?   -  person chrylis -cautiouslyoptimistic-    schedule 11.03.2015
comment
Обязательно посмотрите на Spring Boot; Я использую его для всех моих приложений сейчас. Я рекомендую книгу Грега Тернквиста Learning Spring Boot.   -  person chrylis -cautiouslyoptimistic-    schedule 11.03.2015


Ответы (1)


Вам нужно везде использовать Autowiring, иначе ваша программа не будет работать. Spring может автоматически подключать только bean-компоненты, которые присутствуют в контексте приложения Spring, что и должны делать ваши аннотации @Controller, @Service и @Repository. Однако эти аннотации бессмысленны без тега <context:component-scan base-package="your.base.package"> в XML-файле конфигурации.

Итак, предполагая, что ваш контроллер, служба и DAO находятся где-то в пакете com.repository, вам нужно добавить эту строку в вашу конфигурацию XML.

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

Это говорит Spring рекурсивно искать внутри пакета foo.bar.baz (и всех подпакетов) классы, аннотированные с помощью @Controller, @Service, @Repository и @Component, создавать их экземпляры singleton и делать их доступными для автоматического подключения к другие классы.

Вам также необходимо изменить свой контроллер и классы обслуживания, чтобы использовать @Autowired. Spring не сможет управлять вашими классами, если вы создадите их с помощью ключевого слова new. Эти 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;
    }
}

Обратите внимание, что вы автоматически подключаете свой класс обслуживания к контроллеру.

Ваш класс обслуживания должен реализовать интерфейс. Spring делает всю эту магию автоматического связывания, используя интерфейсы. Вы не можете автоматически связать класс, который не реализует интерфейс, если вы специально не создадите экземпляр этого класса в своей конфигурации XML.

Ваш класс обслуживания должен измениться следующим образом:

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

Как видите, я изменил несколько имен классов, чтобы они лучше соответствовали соглашению Spring. Ваше приложение должно перейти от контроллера к классу обслуживания, затем к DAO и обратно. Это должно работать, если вы выполните шаги, которые я изложил здесь.

Несколько вещей, о которых следует помнить:

  1. Spring ненавидит ключевое слово new. Если вы обнаружите, что используете его, вы, вероятно, делаете что-то не так.
  2. Существует только один экземпляр любого из ваших классов, который Spring выбирает при сканировании компонентов во всем вашем приложении. НЕ используйте эти классы для хранения постоянных данных или состояний. Этот путь полон проблем с потоками, условий гонки и ям, полных кислотных пауков.
  3. Читайте и перечитывайте документацию, это непростые концепции, если вы никогда раньше не использовали Spring. Spring очень прост в использовании, если вы понимаете, как он работает и как он ожидает от вас его использования.
  4. Spring работает с интерфейсами. Если ваш класс не реализует интерфейс, Spring не сможет проксировать его без использования AspectJ Load Time Weaving, о котором стоит поговорить в другой день, а не о том, что вы должны использовать, только начиная. Если вы не знаете, зачем Spring нужно создавать прокси вашего объекта, вам нужно перечитать документацию, пока вы не поймете контекст приложения.
  5. Я переместил аннотацию @Transactional в класс Service. Это связано с тем, что DAO должен заниматься только доступом и извлечением данных из базы данных, а НЕ управлять подключением/сеансом к базе данных, что является задачей класса обслуживания.
  6. #P16# <блочная цитата> #P17# #P18#
  7. Не расстраивайтесь, я столкнулся со всеми этими проблемами, когда пытался научиться использовать Spring, но я справился с этим, и теперь Spring стал для меня второй натурой.
person JamesENL    schedule 10.03.2015
comment
Я ценю вашу помощь, теперь это работает, однако выдает следующее исключение org.hibernate.HibernateException: createQuery недействителен без активной транзакции - person Jack; 10.03.2015
comment
Вы переместили аннотацию @Transactional в свой класс обслуживания? Является ли аннотация фактического метода внутри TestServiceImpl, а не в интерфейсе? Добавьте этот bean-компонент в свою конфигурацию: <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" /> - person JamesENL; 10.03.2015
comment
Как ты это делаешь? Вы используете JUnit или выполняете развертывание на чем-то вроде сервера Tomcat? - person JamesENL; 10.03.2015
comment
Да, я переместил @ Transactional в класс @ Service, и я нахожусь в реальном методе, а не в интерфейсе. Чем хороша эта фасоль? - person Jack; 10.03.2015
comment
развертывание в Tomcat - person Jack; 10.03.2015
comment
Этот bean-компонент переводит HibernateExceptions во что-то, с чем Spring может работать для управления вашими транзакциями. - person JamesENL; 10.03.2015
comment
Теперь, когда я его добавил, похоже, он не может найти сущности. Причина: java.lang.ClassNotFoundException: com.myproject.model.Business - person Jack; 10.03.2015
comment
Давайте продолжим обсуждение в чате. - person Jack; 10.03.2015
comment
Джеймс, я готов поболтать, пожалуйста, дайте мне знать, когда будете свободны. Благодарность - person Jack; 11.03.2015
comment
После этого вопроса stackoverflow.com/ вопросов/26836560/ Я добавил диспетчер транзакций в аннотацию tx:, сначала он выдает исключение, что не может первый объект, который я объявил в hibernate.cfx.xml, а при втором запуске выдает ту же ошибку, что и раньше . - person Jack; 11.03.2015
comment
Давайте продолжим обсуждение в чате. - person Jack; 11.03.2015
comment
пожалуйста, ответьте на вопрос здесь недействителен без активной транзакции"> stackoverflow.com/questions/28976816/ - person Jack; 11.03.2015
comment
Ваши предложения звучат великолепно для тех, кто изучает пружину, особенно последние 7 пунктов. Спасибо. - person zhfkt; 09.03.2016