【问题标题】:How to access Spring Data configured entity manager (factory) in custom implementation如何在自定义实现中访问 Spring Data 配置的实体管理器(工厂)
【发布时间】:2014-12-22 16:48:58
【问题描述】:

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

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

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

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

老实说,Impl 类完全不知道 Spring Data 的事实,尽管在 Spring Data 手册中被描述为一个优势,但当您需要访问通常由 Spring Data 本身在您的自定义实现(几乎总是,我会说...)。

【问题讨论】:

    标签: spring-data spring-data-jpa


    【解决方案1】:

    从 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);
        }
    }
    

    附: 此方法如果您有多个 EntityManager 候选者,则此方法将不起作用,请参阅 JpaContext#getEntityManagerByManagedType -> DefaultJpaContext#getEntityManagerByManagedType 的实现。

    【讨论】:

    • 是的,这是我为此打开的 JIRA 问题DATAJPA-669 的结果。仍然想知道为什么没有提供JpaRepository 中的简单getEntityManager() 方法,它不会有歧义。我在那个 JIRA 问题中对此添加了评论。
    • 随着jira问题DATAJPA-669得到解决,这不应该是公认的答案吗?
    • 这不是给你一个单一的EntityManager 用于在单个持久上下文中定义的所有实体类吗?
    【解决方案2】:

    我能找到的最好的方法是建立一个“约定”:我的存储库声明他们期望一个名为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。

    【讨论】:

      【解决方案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.

      【讨论】:

      • 我确实知道如何配置 Spring Data 存储库(我更喜欢 XML 而不是 Java 配置,顺便说一句),问题是我无法从自定义实现内部知道注入 Spring Data 的内容,除非我在其中“硬编码”了将使用哪个持久性单元的知识。
      猜你喜欢
      • 2014-07-11
      • 1970-01-01
      • 2015-09-01
      • 2021-07-12
      • 1970-01-01
      • 1970-01-01
      • 2013-05-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多