修复 Spring MVC 应用程序中的 Null EntityManger?

发布于 2024-07-19 21:53:54 字数 6096 浏览 10 评论 0原文

在下面的代码中,我的注入的 EnityManager 遇到了麻烦,它总是显示为 null

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 定义。

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

有人能帮我吗?

In the following code I am trouble with my injected EnitityManager, which always shows up as null;

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;
    }
}

Here is the bean definition, defined in dispatcher-servlet.xml.

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

EnitityManager should be injected based on tx:annotation-based, defined in the persistence-context.xml file.

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

The persistence-context is loaded from the 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>

The classpath import is done because the ORM entities are included as a JAR file into the project. Note that I believe the persistence-context is being loaded, as Spring will not allow the application to be deployed if it can't parse its configuration files.

Here is my 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>

And my 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>

Can anyone help me out here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

放手` 2024-07-26 21:53:54

今天我很幸运能够与一位顾问讨论这个问题,他能够帮助我解决整个问题。

所以我的问题是 Spring MVC 正在建立两个不同的上下文,一个应用程序上下文(在 applicationContext.xml 中定义)和一个 Web 上下文(在dispatcher-servlet.xml 中定义)。

来自一个上下文的 Bean 无法与另一上下文中的 Bean 通信,因此,当我在 applicationContext.xml 内初始化持久性上下文时,我无法在由 Dispatcher-servlet.xml(即我的控制器)加载的 Bean 中访问它。

当 Netbeans 自动生成 Spring MVC 的基础时,它会默认设置它。 在一些大型 Web 应用程序中,将应用程序的 Web 部分与其他逻辑(持久性、业务代码等)不同的上下文分开是有意义的。 就我而言,我试图将实体管理器直接自动注入到我的控制器中,这对我不利。

为了解决这个问题,我将行

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

From the applicationContext.xml 移至我的 Dispatcher-servlet.xml。 然后,我的控制器通过 @PersistanceContext 注释正确注入了 EntityManager。

I was lucky enough today to be able to speak with a consultant about this issue, he was able to help me sort the whole thing out.

So my problem is that Spring MVC was establishing two distinct contexts, one application context, defined in applicationContext.xml and one web context, defined in dispatcher-servlet.xml.

Beans from one context can not talk to beans in another context, thus when I initilized my persistence context inside of applicationContext.xml, I could not access it in beans loaded by dispatcher-servlet.xml, ie my controllers.

When Netbeans auto-generated the base to my Spring MVC it set this up by default. In some large web applications, it would make sense to separate the web part of the application in a context distinct from the rest of the logic (persistence, business code, etc). In my case, where I am trying to auto inject my entity manager directly into my controllers, this worked against me.

To fix the issue I moved the line

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

From the applicationContext.xml, to my dispatcher-servlet.xml. My controllers then were properly injected with EntityManagers from the @PersistanceContext annotation.

过潦 2024-07-26 21:53:54

我认为您需要一个文件 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 工厂新名称。

I think you need a file 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>

I think it will not work if the file has a different name, especially not since you don't tell the EntityManager factory the new name anywhere.

反目相谮 2024-07-26 21:53:54

我曾经使用旧的 spring 版本,当您必须将 setProperty() 放入 bean 并在 spring-bean 定义中设置属性标记时,例如:

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

也许您应该使用 transactionManager 或entityManagerFactory beans...

PD:我个人更喜欢注入依赖项的旧方法。

I used to work with an older spring version, when you had to put setProperty() to the bean and set the propery tag inside the spring-bean definition like:

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

Maybe you should work with the transactionManager or the entityManagerFactory beans...

PD: I personally prefer the old way of injecting dependencies.

︶葆Ⅱㄣ 2024-07-26 21:53:54

您是否已将其包含

<context:annotation-config />

在您的 Spring XML 中? 参考此处

Have you included

<context:annotation-config />

In your spring XML. Reference here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文