Spring mvc + hibernate/jpa -> entity manager is no

2019-09-08 05:47发布

问题:

I have a problem with EntityManager. When I try to use EntityManager in a dao class, I got null pointer exception. So EntityManager is not injected despite @PersistenceContext annotation.

My dao:

package com.fido.pia.dao;

import com.fido.pia.model.User;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

@Repository
public class UserDao {

   @PersistenceContext
    protected EntityManager entityManager;

    public User save(User row) {
        if(row.isNew()) {
            entityManager.persist(row);
            return row;
        } else {
            return entityManager.merge(row);
        }
    }
}

Servlet Config:

<?xml version="1.0" encoding="UTF-8"?>

<beans  xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 
    Adds some default beans (HandlerAdapter, HandlerMapping, Binding Initializer...). It also turn on some annotations. 
    Explanation in http://stackoverflow.com/questions/28851306/spring-framework-what-is-the-purpose-of-mvcannotation-driven

    WITHOUT THIS, @RequestMapping ANNOTATIONS ARE LOADED, BUT MAPPING DO NOT WORK!!
    -->
    <mvc:annotation-driven />

<!--    Set loading annotations from classes
    <context:component-scan base-package="com.fido.pia"/>-->

    <!--manual homepage-->
    <mvc:view-controller path="/" view-name="home"/>

    <!--view resolver-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <!--static resources - request will be handeled by ResourceHttpRequestHandler-->
    <mvc:resources mapping="/resources/**" location="/resources/" />

    <!--database config-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/pia" />
        <property name="username" value="root" />
        <property name="password" value="" />
    </bean>

    <!--entity manager factory-->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="packagesToScan" value="com.fido.pia" />
        <property name="dataSource" ref="dataSource" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <!--<property name="generateDdl" value="true" />-->
                <property name="showSql" value="true" />
            </bean>
        </property>
    </bean>

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

    <!-- enable the configuration of transactional behavior based on annotations -->
    <tx:annotation-driven transaction-manager="transactionManager" />

    <!--Set loading annotations from classes-->
    <context:component-scan base-package="com.fido.pia"/>
</beans>

Any ideas what is wrong here?

回答1:

In entityManagerFactory bean definition, try this :

<property name="packagesToScan" value="com.fido.pia.*" />

This should work



回答2:

I finally solve it. The problem was that I use common dependency injection to inject my dao class in controller. When I change it to DI with autowired (added @autowired to controller constructor), entity manager in dao is initialized.

So now it works, but I'm still curious about why is that change so important. I've asked new question about it.



回答3:

You need to enable persistence annotations:

<context:annotation-config/>

or

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