在 Spring 上实例化 EntityManager

Posted

技术标签:

【中文标题】在 Spring 上实例化 EntityManager【英文标题】:Instantiate EntityManager over Spring 【发布时间】:2014-07-03 07:54:20 【问题描述】:

我在底层 hsqld 上的 spring 3.2.2 应用程序中使用实体管理器:

@Transactional
public class TestDaoImpl implements PersonDao 

    /**
     * Logger
     */
    private static final Logger log = Logger.getLogger(TestDaoImpl.class);

    @PersistenceContext    
    private EntityManager em;

    /**
     * @param em
     */
    public TestDaoImpl() 
        super();
    

    @Override
    public List<Person> getAll() 
        log.info("get all DAO");

        //TODO fix query!!!
        List<Person> resultList = em.createQuery("SELECT * FROM Person;", Person.class).getResultList(); 

        log.info(resultList.toString());

        return resultList;

    

我的pom.xmldependencies:

<dependencies>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.2.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>3.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>3.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>3.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <version>2.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-tools</artifactId>
            <version>3.2.0.ga</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-annotations</artifactId>
            <version>3.5.6-Final</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.4</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
    </dependencies>

我的问题是我的EntityManager em 为空。因此,实体管理器不会被 spring 注入。这是我的应用程序上下文:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/aop
                        http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
                        http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-3.2.xsd
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

    <tx:annotation-driven />
    <context:annotation-config />

    <bean id="mainGUI" class="com.testApp.MainWindow" />

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
        <property name="url" value="jdbc:hsqldb:hsql://localhost/testDB" />
        <property name="username" value="sa" />
        <property name="password" value="" />
        <property name="initialSize" value="5" />
        <property name="maxActive" value="10" />
    </bean>

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="persistenceUnitName" value="jpaData" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">false</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>

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

任何建议为什么我的应用程序上下文没有被实例化? Spring 和 hibernate 加载正确!

更新

我把我的班级改成:

@Transactional
@Repository
public class TestDaoImpl implements PersonDao 

    private static final Logger log = Logger.getLogger(PersonDaoImpl.class);

    @PersistenceContext    
    public EntityManager em;

    public TestDaoImpl() 
        super();
    

    @Override
    public List<Person> getAll() 
        log.info("get all DAO");

        //TODO fix query!!!
        List<Person> resultList = em.createQuery("SELECT * FROM Person;", Person.class).getResultList(); 

        log.info(resultList.toString());

        return resultList;

    

但是,我仍然在以下位置收到异常 java.lang.NullPointerException

em.createQuery("SELECT * FROM Person;", Person.class).getResultList();

调试器显示,em 仍然为空。

更新

我的日志文件:

0    [main] INFO  com.Application.main.startGUI  - set look and feel
775  [main] INFO  org.springframework.context.support.ClassPathXmlApplicationContext  - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@291aff: startup date [Thu Jul 03 10:22:25 CEST 2014]; root of context hierarchy
854  [main] INFO  org.springframework.beans.factory.xml.XmlBeanDefinitionReader  - Loading XML bean definitions from class path resource [applicationContext.xml]
1383 [main] INFO  org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean  - Building JPA container EntityManagerFactory for persistence unit 'jpaData'
1546 [main] INFO  org.hibernate.annotations.common.Version  - HCANN000001: Hibernate Commons Annotations 4.0.1.Final
1551 [main] INFO  org.hibernate.Version  - HHH000412: Hibernate Core 4.2.0.Final
1553 [main] INFO  org.hibernate.cfg.Environment  - HHH000206: hibernate.properties not found
1554 [main] INFO  org.hibernate.cfg.Environment  - HHH000021: Bytecode provider name : javassist
1576 [main] INFO  org.hibernate.ejb.Ejb3Configuration  - HHH000204: Processing PersistenceUnitInfo [
    name: jpaData
    ...]
1859 [main] INFO  org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator  - HHH000130: Instantiating explicit connection provider: org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider
2593 [main] INFO  org.hibernate.dialect.Dialect  - HHH000400: Using dialect: org.hibernate.dialect.HSQLDialect
2624 [main] INFO  org.hibernate.engine.transaction.internal.TransactionFactoryInitiator  - HHH000268: Transaction strategy: org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory
2630 [main] INFO  org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory  - HHH000397: Using ASTQueryTranslatorFactory
2971 [main] INFO  org.hibernate.tool.hbm2ddl.SchemaUpdate  - HHH000228: Running hbm2ddl schema update
2971 [main] INFO  org.hibernate.tool.hbm2ddl.SchemaUpdate  - HHH000102: Fetching database metadata
2975 [main] INFO  org.hibernate.tool.hbm2ddl.SchemaUpdate  - HHH000396: Updating schema
3002 [main] INFO  org.hibernate.tool.hbm2ddl.TableMetadata  - HHH000261: Table found: PUBLIC.PUBLIC.READATA
3002 [main] INFO  org.hibernate.tool.hbm2ddl.TableMetadata  - HHH000037: Columns: [budgetednetrentalrevenuespernetsalesrevenues, marketrisklevel, installmentsontotalfacilityineurforyear10, totcom_9, totcom_8, totcom_7, customer, city, cashcollateral, leasecontractcurrency, cncy, projnr, maturitydate, usetype, totalnla, userisklevel, actualnetrentalrevenuespernetsalesrevenues, country, gccnr, che, market, totcom_10, percentagerentalincomeforyear8, percentagerentalincomeforyear7, avbinc_10, percentagerentalincomeforyear9, percentagerentalincomeforyear4, percentagerentalincomeforyear3, percentagerentalincomeforyear6, tic_contractcurrency, percentagerentalincomeforyear5, installmentsontotalfacilityincontractcurrencyforyear10, percentagerentalincomeforyear2, percentagerentalincomeforyear1, defaultrisklevel, avbinc_7, avbinc_6, installmentsontotalfacilityincontractcurrencyforyear9, avbinc_9, installmentsontotalfacilityincontractcurrencyforyear8, avbinc_8, installmentsontotalfacilityincontractcurrencyforyear7, avbinc_3, installmentsontotalfacilityincontractcurrencyforyear6, avbinc_2, installmentsontotalfacilityincontractcurrencyforyear5, avbinc_5, avbinc_4, installmentsontotalfacilityincontractcurrencyforyear4, installmentsontotalfacilityincontractcurrencyforyear3, externalcommitment, installmentsontotalfacilityincontractcurrencyforyear2, avbinc_1, installmentsontotalfacilityincontractcurrencyforyear1, id, installmentsontotalfacilityineurforyear8, installmentsontotalfacilityineurforyear7, installmentsontotalfacilityineurforyear9, locqual, repaysou, marketvalue_contractcurrency, installmentsontotalfacilityineurforyear1, installmentsontotalfacilityineurforyear2, refinancingrate, installmentsontotalfacilityineurforyear5, installmentsontotalfacilityineurforyear6, installmentsontotalfacilityineurforyear3, installmentsontotalfacilityineurforyear4, actualnla, externalcommitmentinpecentage, projstat, totcom_1, totcom_2, percentagerentalincomeforyear10, totcom_3, totcom_4, projectstatusrisklevel, totcom_5, totcom_6]
3002 [main] INFO  org.hibernate.tool.hbm2ddl.TableMetadata  - HHH000108: Foreign keys: []
3002 [main] INFO  org.hibernate.tool.hbm2ddl.TableMetadata  - HHH000126: Indexes: [sys_idx_sys_pk_10114_10115]
3006 [main] INFO  org.hibernate.tool.hbm2ddl.TableMetadata  - HHH000261: Table found: PUBLIC.PUBLIC.SCENARIOBASE
3006 [main] INFO  org.hibernate.tool.hbm2ddl.TableMetadata  - HHH000037: Columns: [id, others, see, year, cee, we]
3006 [main] INFO  org.hibernate.tool.hbm2ddl.TableMetadata  - HHH000108: Foreign keys: []
3007 [main] INFO  org.hibernate.tool.hbm2ddl.TableMetadata  - HHH000126: Indexes: [sys_idx_sys_pk_10117_10118]
3007 [main] INFO  org.hibernate.tool.hbm2ddl.SchemaUpdate  - HHH000232: Schema update complete
3068 [main] INFO  org.springframework.beans.factory.support.DefaultListableBeanFactory  - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@7a1576: defining beans [org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,personBaseDaoImpl,mainGUI,dataSource,entityManagerFactory,transactionManager,entityManager,org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor#0,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
3402 [AWT-EventQueue-0] INFO  com.Application.gui.personSelection.MainWindow  - make Layout
3402 [AWT-EventQueue-0] INFO  com.Application.gui.personSelection.MainWindow  - add Menue Bar
3413 [AWT-EventQueue-0] INFO  com.Application.gui.personSelection.MainWindow  - add Tab Bar
3416 [AWT-EventQueue-0] INFO  com.Application.gui.personSelection.MainTabPanel  - enterMainTabPanel create Layout method
3420 [AWT-EventQueue-0] INFO  com.Application.gui.personSelection.PersonSelectionPanel  - enter placeSelectionWithButtons method
3511 [AWT-EventQueue-0] INFO  com.Application.gui.accronData.GUITabPanel  - enter GUITabPanel create Layout method
3514 [AWT-EventQueue-0] INFO  com.Application.service.PersonBaseServiceImpl  - reveiving all data in the person base service
3514 [AWT-EventQueue-0] INFO  com.Application.dao.PersonBaseDaoImpl  - get all DAO
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at com.Application.dao.PersonBaseDaoImpl.getAll(PersonBaseDaoImpl.java:51)
    at com.Application.service.PersonBaseServiceImpl.getAll(PersonBaseServiceImpl.java:45)
    at com.Application.gui.accronData.GUIDataPanel.<init>(GUIDataPanel.java:42)
    at com.Application.gui.accronData.GUITabPanel.createLayout(GUITabPanel.java:42)
    at com.Application.gui.personSelection.MainWindow.createTabBar(MainWindow.java:159)
    at com.Application.gui.personSelection.MainWindow.makeLayout(MainWindow.java:182)
    at com.Application.gui.personSelection.MainWindow.access$1(MainWindow.java:173)
    at com.Application.gui.personSelection.MainWindow$4.run(MainWindow.java:196)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$400(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

更新

我的PersonBaseServiceImpl

public class PersonBaseServiceImpl implements PersonBaseService 

    /**
     * Logger
     */
    private static final Logger log = Logger.getLogger(PersonBaseServiceImpl.class);

    /**
     * PersonBaseDAO Access
     */
    private TestDao testBaseDAO; // TestDao is an interface to my TestDaoImpl class

    /**
     * Constructor
     * @param scenarioBaseDAO
     */
    public PersonBaseServiceImpl()
        this.testBaseDAO = new TestDaoImpl();

    

    @Override
    public List<PersonBase> getAll() 
        log.info("reveiving all data in the scenario base service");

        return testBaseDAO.getAll();
    


【问题讨论】:

TestDaoImpl 是如何使用的?您是否将其注入测试?如果有,怎么做? @geoand 感谢您的回答!我基本上是在服务层创建一个实例。请看我的日志文件!我也调试了我的应用,发现em为null,所以我想在我的db上创建的查询无法使用;(。非常感谢您的回复! 你能发帖PersonBaseServiceImpl吗? @geoand 感谢您的回答!请查看我的最新更新。 【参考方案1】:

问题是您自己实例化PersonBaseDao(使用new),并让Spring 管理它的生命周期。

您需要在 PersonBaseDao 上使用 @Autowired 并使用构造型注释(可能是 @Service)制作 PersonBaseServiceImpl 和 Spring 托管组件。

当然,这同样适用于您在调用 PersonBaseServiceImpl 的任何组件中使用它的方式

【讨论】:

【参考方案2】:

你错过了 DAO 中的 @Repository 注释。

【讨论】:

我必须用@Repository 注释替换@Transactional 注释吗? 我也可以用@Component代替上面的两个吗?非常感谢您的回复! @Vivien 不,你可以同时添加两个注释 @Vivien Plaese 还将 '` 添加到您的应用程序上下文中。 @Vivien 启动应用程序时日志文件中是否有任何异常

以上是关于在 Spring 上实例化 EntityManager的主要内容,如果未能解决你的问题,请参考以下文章

8. Spring 注解开发(原始注解)2

Spring中四种实例化bean的方式

Spring实例化bean的三种方式

无法在 GoCD 上实例化测试容器

Spring系列(一)Spring MVC bean 解析、注册、实例化流程源码剖析

Spring- Bean的实例化