7

有谁知道如何通过 @PersistenceUnit 注释通过构造函数设置 EntityManagerFactory 。我可以通过xml配置来做到这一点。但是我不知道对应的注解配置。

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
  <bean
    class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml" />
<property name="persistenceUnitName" value="myUnit"></property>

<bean id="handler" class="com.handler.LocalHTHandler">
<constructor-arg ref="entityManagerFactory"></constructor-arg>

它工作正常。我们可以通过我的处理程序 bean 的注释来做到这一点吗?我听说过 @persistanceunit ,但它不能放在构造函数中来实现它。那是对的吗?

4

5 回答 5

4

目前,Spring 团队表示可以EntityManager通过构造函数注入,因为他们已经在 Spring JPA Repository 上使用了。

只是:

private final EntityManager em;

public YourRepository(EntityManager em) {
    this.em = em;
}

我测试过。作品:)。不再有现场注入。

于 2018-04-20T19:12:08.217 回答
4

正如@Dherik 所说,您可以通过构造函数执行此操作。下面的多数据源示例(在 SpringBoot 2.0.4 上测试):

SomeRepository.java

@Repository
public class SomeRepository {

    private final EntityManager entityManager;

    public TestService(@Qualifier("someEntityManagerFactory") EntityManager entityManager) {
        this.entityManager = entityManager;
    }
}

SomeDatabaseConfig.java

import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.orm.jpa.vendor.HibernateJpaDialect;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "someEntityManagerFactory")
@EnableConfigurationProperties(JpaProperties.class)
class SomeDatabaseConfig {

    private static final String PERSISTENCE_UNIT = "some";
    private static final String[] PACKAGES_TO_SCAN = {"package.where.you.store.your.entities"};

    @Bean(name = "someDataSourceProps")
    @ConfigurationProperties("some.datasource")
    DataSourceProperties dataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean(name = "someDataSource")
    DataSource dataSource(@Qualifier("someDataSourceProps") DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
    }

    @Bean(name = "someEntityManagerFactory")
    LocalContainerEntityManagerFactoryBean entityManagerFactory(
            JpaProperties jpaProperties,
            @Qualifier("someDataSource") DataSource dataSource,
            @Qualifier("someJpaVendorAdapter") JpaVendorAdapter jpaVendorAdapter) {
        return createEntityManagerFactory(jpaProperties, dataSource, jpaVendorAdapter, PERSISTENCE_UNIT, PACKAGES_TO_SCAN);
    }

    @Bean("someJpaVendorAdapter")
    JpaVendorAdapter jpaVendorAdapter(JpaProperties jpaProperties) {
        final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setShowSql(jpaProperties.isShowSql());
        return vendorAdapter;
    }

    @Bean(name = "someTransactionManager")
    PlatformTransactionManager transactionManager(@Qualifier("someEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

    static LocalContainerEntityManagerFactoryBean createEntityManagerFactory(JpaProperties jpaProperties, DataSource dataSource, JpaVendorAdapter jpaVendorAdapter, String persistenceUnit, String[] packagesToScan) {
        final LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        factoryBean.setJpaDialect(new HibernateJpaDialect());
        factoryBean.setJpaPropertyMap(getVendorProperties(jpaProperties));
        factoryBean.setPersistenceUnitName(persistenceUnit);
        factoryBean.setPackagesToScan(packagesToScan);
        return factoryBean;
    }

    private static Map<String, Object> getVendorProperties(JpaProperties jpaProperties) {
        return jpaProperties.getHibernateProperties(new HibernateSettings());
    }
}

应用程序.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;

@SpringBootApplication(
        exclude = {
                DataSourceAutoConfiguration.class,
                HibernateJpaAutoConfiguration.class,
                DataSourceTransactionManagerAutoConfiguration.class
        }
)
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
于 2018-08-23T15:48:49.710 回答
3

使用 JSR 330 注释的 Spring 是不可能的。目前不可能将 EntityManagers 注入到构造函数中,因为@PersistenceContext定义为不允许在参数上使用。请参阅JPA_SPEC-72允许通过构造函数注入(以及一般在非@PersistenceContext 注入点)注入 EntityManagers [SPR-10443]

于 2017-02-14T10:07:32.410 回答
1

如果您出于某种原因不想在项目中使用 Spring Data(例如,您只是让遗留项目更好一点),您可以创建以下内容FactoryBeanEntityManager通过构造函数注入进行注入:

/**
 * Makes the {@link EntityManager} injectable via <i>@Autowired</i>,
 * so it can be injected with constructor injection too.
 * (<i>@PersistenceContext</i> cannot be used for constructor injection.)
 */
public static class EntityManagerInjectionFactory extends AbstractFactoryBean<EntityManager> {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public Class<?> getObjectType() {
        return EntityManager.class;
    }

    @Override
    protected EntityManager createInstance() {
        return entityManager;
    }

}

请注意,因为我们在@PersistenceContext内部使用注释,所以返回的EntityManager将是一个适当的线程安全代理,因为它会直接在使用字段注入的地方注入。

于 2021-02-06T09:48:58.447 回答
0

在我们的代码中,我们有一个基础 dao 对象,它通过 PersistenceContext 使用注入的实体管理器:

public abstract class BasicJpaDao<T> implements IBasicDao<T> {

    @PersistenceContext(type = PersistenceContextType.TRANSACTION, unitName = "default")
    protected EntityManager entityManager;

    // Default constructor for Spring
    public BasicJpaDao() {}

    //Use this constructor to set the entity manager yourself
    public BasicJpaDao(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    ...

}

持久性单元在 Application Context 文件中定义,如下所示:

<!-- JPA -->
<!-- Creates an EntityManagerFactory for use with the Hibernate JPA provider -->
<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSourceGlobal" />
    <property name="packagesToScan" value="me.comocomo.nutrino.domain.jpa" />
    <property name="jpaVendorAdapter" ref="jpaVendorAdapter" />

    <property name="jpaPropertyMap">
        <map merge="true">
            <entry key="hibernate.format_sql" value="${hibernate.format_sql}" />
        </map>
    </property>
</bean>

<!-- jpaVendorAdapter (works in conjunction with the persistence.xml) -->
<bean id="jpaVendorAdapter"
    class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <property name="database" value="${jpa.database}" />
    <property name="showSql" value="${jpa.showSql}" />
    <property name="databasePlatform" value="${jpa.dialect}" />
    <property name="generateDdl" value="${jpa.generateDdl}" />
</bean>

<!-- In order to enable EntityManager injection -->
<bean id="persistenceAnnotation"
    class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

<!-- Transactions -->
<tx:annotation-driven transaction-manager="transactionManager" />

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

类似地,您可以创建一个 EntityManagerFactoryFactory 类,该类使用 Injection 获取 EntityManagerFactory,然后将工厂传递给您的 bean:

@Component
public class EntityManagerFactoryFactory {

    @Inject
    private EntityManagerFactory factory;
}
于 2013-07-29T07:02:15.620 回答