16

根据其 JavaDoc,PersistenceAnnotationBeanPostProcessor 似乎负责使用注解 @PersistenceContext 注入 EntityManager。它似乎暗示没有在 Spring 应用程序上下文 xml 中声明此 bean,@PersistenceContext 注释将不起作用。

然而,根据我的实验,事实并非如此。

持久性.xml

<persistence 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"
    version="1.0">
    <persistence-unit name="default" transaction-type="RESOURCE_LOCAL" />
</persistence>

Spring 应用程序上下文 XML

<context:component-scan base-package="com.test.dao" />

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

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver"/>
    <property name="url" value="jdbc:derby://localhost:1527/c:\derbydb\mydb"/>
    <property name="username" value="APP"/>
    <property name="password" value="APP"/>
</bean>

<tx:annotation-driven/>

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

<!-- 
    <bean id="persistenceAnnotation" class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
 -->

UserDaoImpl

@Repository("userDao")
public class UserDaoImpl implements UserDao {

    @PersistenceContext
    protected EntityManager entityManager;

    @Transactional
    public void save(User user) {
            entityManager.persist(user);
    }
}

无论我注释或取消注释persistenceAnnotation bean,结果都是一样的。把豆子留在身边并没有什么坏处,但是这个豆子有什么用呢?

我正在使用 Spring 3.0.5。

有人可以提供一个场景,取出这个 bean 会导致失败吗?

我也不喜欢仅仅为了愚弄 Spring 而创建一个空的持久性单元。幸运的是,这个问题已经在 Spring 3.1.0 中得到解决。

4

2 回答 2

16

由元素PersistenceAnnotationBeanPostProcessor透明激活。<context:component-scan />准确地说,它<context:annotation-config />是激活 bean 的元素,但这个元素又被透明地激活<context:component-scan />

于 2012-09-19T12:18:36.333 回答
7

正如 Oliver Gierke 所提到的,org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor当使用基于注释的配置时,Spring 会自动将其加载到 App Context 中。它的职责之一是搜索EntityManagerFactory可以EntityManager为您提供@PersistenceContext注释属性的适当实体。

如果你EntityManagerFactory的spring config/context中有多个bean并且你有@PersistenceContext没有属性的注释unitName(假设你正在使用一个带有这样一个bean的框架,并且你不能接触框架代码),你可能会遇到这个异常:org.springframework.beans.factory.NoUniqueBeanDefinitionException.

我找到了这个解决方法,以防你进入这个:

<bean id="org.springframework.context.annotation.internalPersistenceAnnotationProcessor"
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" >
<property name="defaultPersistenceUnitName" value="entityManagerFactory"/>
</bean> 

这将覆盖PersistenceAnnotationBeanPostProcessorSpring 加载的默认值,并使用defaultPersistenceUnitName.

于 2014-07-28T15:25:13.440 回答