如何在自定义实现中访问Spring Data配置的实体管理器(工厂)

时间:2014-12-22 16:48:59

标签: spring-data spring-data-jpa

我正在为Spring Data JPA存储库编写自定义实现。所以我有:

  • MyEntityRepositoryCustom =>界面与自定义方法
  • MyEntityRepositoryUmpl =>实现上述接口
  • MyEntityRepository =>扩展JpaRepositoryMyEntityRepositoryCustom
  • 的标准界面

我的问题是:在MyEntityRepositoryUmpl的实现中,我需要访问注入Spring Data的实体管理器。怎么弄? 我可以使用@PersistenceContext使其自动装配,但问题是此存储库必须在设置多个持久性单元的应用程序中工作。所以,要告诉Spring我需要哪一个,我必须使用@PersistenceContext(unitName="myUnit")。但是,由于我的存储库是在可重用的服务层中定义的,因此我无法知道更高级别的应用程序层将配置为注入我的存储库的持久性单元的名称。

换句话说,我需要做的是访问Spring Data本身正在使用的实体管理器,但是在查看Spring Data JPA文档(不那么快)之后我找不到任何东西。< / p>

老实说,Impl类完全没有意识到Spring Data,虽然在Spring Data手册中被描述为一个优势,但实际上每当你需要访问通常由Spring Data本身提供的东西时都是一个复杂的事实。在你的自定义实现中(几乎总是,我会说......)。

3 个答案:

答案 0 :(得分:21)

从Spring Data JPA 1.9.2版本开始,您可以通过JpaContext访问EntityManager,请参阅:http://docs.spring.io/spring-data/jpa/docs/1.9.2.RELEASE/reference/html/#jpa.misc.jpa-context。 例如:

@Component
public class RepositoryUtil
{
    @Autowired
    private JpaContext jpaContext;

    public void deatach(T entity)
    {
        jpaContext.getEntityManagerByManagedType(entity.getClass()).detach(entity);
    }
}

P.S。 如果某个类有多个EntityManager候选,则此方法将无效,请参阅JpaContext#getEntityManagerByManagedType - &gt;的实现。 DefaultJpaContext#getEntityManagerByManagedType。

答案 1 :(得分:4)

我能找到的最好的是建立一个“约定”:我的存储库声明他们希望一个名为myConventionalPU的持久性单元可用。然后,应用程序层将该别名分配给它设置并注入Spring Data的实体管理器工厂,因此我的自定义实现可以使用该别名通过自动装配接收正确的EMF。以下是我的应用程序上下文的摘录:

<bean id="myEntityManagerFactory" name="myConventionalPU" 
  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  [...]
</bean>

<jpa:repositories base-package="com.example"
  entity-manager-factory-ref="myEntityManagerFactory"
  transaction-manager-ref="transactionManager" />

在我的自定义实现中:

@PersistenceContext(unitName = "myConventionalPU")
private EntityManager em;

我根据此要求打开了DATAJPA-669

答案 2 :(得分:3)

Spring Data JPA使用Auto配置类自动生成entityManagerFactory,dataSource和transactionManager。

如果要访问entityManager并控制实例化和设置,则需要定义自己的PersistenceConfiguration。以下是使用Java Config

的示例代码
    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(basePackages = { "com.test.repositories.*" })
    public class PersistenceJpaConfig {

        @Autowired
        JpaVendorAdapter jpaVendorAdapter;

        @Bean
        public DataSource dataSource() {
            return new EmbeddedDatabaseBuilder()
                    .setName("testdb")
                    .setType(EmbeddedDatabaseType.HSQL)
                    .build();
        }

        @Bean
        public EntityManager entityManager() {
            return entityManagerFactory().createEntityManager();
        }

        @Bean
        public EntityManagerFactory entityManagerFactory() {
            LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
            lef.setDataSource(dataSource());
            lef.setJpaVendorAdapter(jpaVendorAdapter);
            lef.setPackagesToScan("com.test.domain.*");
            lef.afterPropertiesSet();
            return lef.getObject();
        }

        @Bean
        public PlatformTransactionManager transactionManager() {
            return new JpaTransactionManager(entityManagerFactory());
        }
    }

如果您有多个数据源,follow this article.