Исправить Null EntityManger в приложении Spring MVC?
В следующем коде у меня проблемы с моим введенным 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 ответа
Сегодня мне посчастливилось поговорить с консультантом по этому вопросу, он помог мне разобраться в этом.
Поэтому моя проблема заключается в том, что 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.
Раньше я работал с более старой версией Spring, когда вам приходилось помещать setProperty() в bean-компонент и устанавливать тег Propery внутри определения Spring-bean следующим образом:
<bean id="Generic" class="com.application.web.GenericController" />
<property name="em" ref="entityManager" />
</bean>
Возможно, вам следует поработать с компонентом TransactionsManager или компонентом entityManagerFactory...
П.Д.: Я лично предпочитаю старый способ введения зависимостей.
Я думаю тебе нужен файл 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 новое имя в любом месте.