Исправить Null EntityManger в приложении Spring MVC? - PullRequest
7 голосов
/ 20 мая 2009

В следующем коде у меня проблемы с введенным EnitityManager, который всегда отображается как ноль ;

public class GenericController extends AbstractController {

    @PersistenceContext(unitName = "GenericPU")
    private EntityManager em;

    protected ModelAndView handleRequestInternal(
            HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        //(em == null) is always trigged
        if (em == null) throw new NullPointerException("em is null");
        Collection<Generic> Generics = em.createNamedQuery("Generic.findAll").getResultList();

        ModelAndView mav = new ModelAndView("Generic");
        mav.addObject(Generics); 
        return mav;
    }
}

Вот определение компонента, определенное в dispatcher-servlet.xml .

<bean id="Generic" class="com.application.web.GenericController" />

EnitityManager должен вводиться на основе tx: annotation-based, определенного в файле persistence-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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
        <property name="url" value="removed" />
        <property name="username" value="removed" />
        <property name="password" value="removed" />
    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="GenericPU" />
        <property name="dataSource" ref="dataSource" />
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
        </property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true" />
                <property name="generateDdl" value="false" />
                <property name="databasePlatform" value="org.hibernate.dialect.SQLServerDialect" />
            </bean>
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

</beans> 

Постоянный контекст загружается из applicationContext.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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">    
    <import resource="classpath:META-INF/persistence-context.xml"/>
</beans>

Импорт пути к классам выполнен, потому что объекты ORM включены в проект в виде файла JAR. Обратите внимание, что я считаю, что постоянный контекст загружается, поскольку Spring не разрешит развертывание приложения, если оно не сможет проанализировать свои файлы конфигурации.

Вот мой persistence.xml .

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
  <persistence-unit name="CoolOrmJpaPU" transaction-type="RESOURCE_LOCAL">
    <class>com.application.orm.jpa.Generic</class>
    <!-- bunch more classes -->
  </persistence-unit>
</persistence>

И мой web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>redirect.jsp</welcome-file>
    </welcome-file-list>
</web-app>

Может кто-нибудь помочь мне здесь?

Ответы [ 4 ]

8 голосов
/ 20 мая 2009

Мне посчастливилось сегодня поговорить с консультантом по этому вопросу, он смог помочь мне разобраться в этом.

Итак, моя проблема в том, что Spring MVC устанавливал два отдельных контекста , один контекст приложения, определенный в applicationContext.xml, и один веб-контекст, определенный в dispatcher-servlet.xml.

Бины из одного контекста не могут общаться с бинами в другом контексте, поэтому, когда я инициализировал свой контекст персистентности внутри applicationContext.xml, я не мог получить к нему доступ в бинах, загруженных dispatcher-servlet.xml, т.е. моими контроллерами. *

Когда Netbeans автоматически генерировал базу для моего Spring MVC, он настраивал ее по умолчанию. В некоторых крупных веб-приложениях имеет смысл разделять веб-часть приложения в контексте, отличном от остальной логики (постоянство, бизнес-код и т. Д.). В моем случае, когда я пытаюсь автоматически внедрить моего менеджера сущностей непосредственно в мои контроллеры, это сработало против меня.

Чтобы исправить проблему, я переместил строку

<import resource="classpath:META-INF/persistence-context.xml"/>

Из applicationContext.xml в мой dispatcher-servlet.xml. Затем мои контроллеры были правильно добавлены с EntityManager из аннотации @PersistanceContext.

0 голосов
/ 20 мая 2009

Раньше я работал с более старой версией Spring, когда вам приходилось помещать setProperty () в bean-компонент и устанавливать тег Propery в определении Spring-компонента следующим образом:

<bean id="Generic" class="com.application.web.GenericController" />
    <property name="em" ref="entityManager" />
</bean>

Может быть, вам стоит поработать с компонентом TransactionsManager или entityManagerFactory ...

PD: лично я предпочитаю старый способ внедрения зависимостей.

0 голосов
/ 20 мая 2009

Вы включили

<context:annotation-config />

В твоей весне XML. Ссылка здесь

0 голосов
/ 20 мая 2009

Я думаю, вам нужен файл persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
    xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">

  <persistence-unit name="GenericPU">
     <class>com.domain.MyClass</class>
  </persistence-unit>

</persistence>

Я думаю, что это не будет работать, если файл имеет другое имя, особенно если вы не сообщаете фабрике EntityManager новое имя.

...