为什么Spring ORM JpaTransactionManager使用本机实体管理器工厂?

时间:2018-08-30 11:40:58

标签: java spring hibernate spring-data-jpa spring-orm

使用本机对象创建实体管理器jps交易时,是否有任何特定原因?

   EntityManagerFactory emf = this.getEntityManagerFactory();
   if (emf instanceof EntityManagerFactoryInfo) {
            emf = 
           ((EntityManagerFactoryInfo)emf).getNativeEntityManagerFactory();
   }

我们的要求是使用Proxy(Created)代替本机对象,我们围绕getSession方法创建了方面,以便动态添加租户id(Discriminator Column)进行查询

谢谢, 毗湿奴

1 个答案:

答案 0 :(得分:0)

要点解释:

JpaTransactionManager createEntityManagerForTransaction()方法中解包本机EntityManagerFactory的原因是,仍然使用代理会在以后创建扩展 > EntityManager,而不是交易范围的实体。对于常规的交易会话,后者是我们想要的。

如果我们仍然使用代理会发生什么:

因为代理将所有调用委派给 ManagedEntityManagerFactoryInvocationHandler ,所以我们也希望委派对 createEntityManager()的调用,我们希望从该调用中获得交易范围的实体管理器。
如果我们看一下上述处理程序的 invoke()方法的实现,我们会发现它从 AbstractEntityManagerFactoryBean 调用 invokeProxyMethod()看到它专门触发了扩展事务管理器的创建,而不是事务范围的管理器的创建。这可能只是Spring开发人员的设计选择。

Object invokeProxyMethod(Method method, @Nullable Object[] args) throws Throwable {
    // unrelated code here
    if (method.getName().equals("createEntityManager") && args != null && args.length > 0 &&
            args[0] == SynchronizationType.SYNCHRONIZED) {
        EntityManager rawEntityManager = (args.length > 1 ?
                getNativeEntityManagerFactory().createEntityManager((Map<?, ?>) args[1]) :
                getNativeEntityManagerFactory().createEntityManager());
        // we get an extended entity manager
        return ExtendedEntityManagerCreator.createApplicationManagedEntityManager(rawEntityManager, this, true);
    }
    // more unrelated code here
    Object retVal = method.invoke(getNativeEntityManagerFactory(), args);
    if (retVal instanceof EntityManager) {
        EntityManager rawEntityManager = (EntityManager) retVal;
        retVal = ExtendedEntityManagerCreator.createApplicationManagedEntityManager(rawEntityManager, this, false);
    }
    // in the final path, we also get an extended entity manager
    return retVal;
}

我会尝试一些方法来规避您的问题:

您可以尝试对 JpaTransactionManager 进行子类化,并使用最小的更改覆盖 createEntityManagerForTransaction(),这些更改将在以后适应您对方面的使用。但是,由于上述与扩展实体管理器有关的解释,仅不展开EntityManagerFactory代理可能就不是您想要的。

您可能要研究的另一件事是更改您提到的方面,以使其不需要使用Spring的entityManagerFactory代理,并且可以与本机对象一起正常使用。作为最后的选择,您可以尝试子类化并覆盖此解决方案中提到的多个Spring ORM类的方法,以便适应Spring的行为和各个方面。