java - 如何将 jpa 存储库初始化从启动时间移动到 Multi-Tenancy 环境的 session 创建时间

标签 java spring hibernate spring-data multi-tenant

我正在将 Jpa 存储库与我的具有 Multi-Tenancy 支持的项目集成。因此,每当请求到来时,我们都会在本地线程中设置一个租户 ID,如下所示 -

public class AccessFilter implements Filter{
 @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//
UserContext userContext = (UserContext) session.getAttribute(USER_CONTEXT);
TenantContext.set(userContext.getTenantId());

//
}
}

我的jpa配置是这样的

`<jpa:repositories base-package="com.adnan" factory-class="com.spmsoftware.appframework.repository.MyRepositoryFactoryBean"`  />

当我部署开始扫描包并尝试将实体管理器和事务管理器注入(inject) JpaRepositoryFactoryBean 时,但由于 AccessFilter 尚未调用(因为它将在创建 session 时调用),因此在线程本地中未设置租户 Id 并且失败。我的 EntityManagerFactory 代码是这样的 -

@Override
    public EntityManagerFactory getEntityManagerFactory() {
        return threadLocalHasFactory.get();
    }

我已经浏览过http://codecrafters.blogspot.sk/2013/03/multi-tenant-cloud-applications-with.html但这家伙使用 Apache Shiro 框架,但在我的例子中没有使用。 我不确定的是,如何将整个 jpa 存储库创建逻辑从启动时间移动到创建 session 时。 我正在使用 Hibernate4 和 Spring 3。 如果有人需要更多信息,请告诉我。

最佳答案

我找到了解决方案,可能是这里的工作共享。

我已经删除了存储库类的 Autowiring ,并开始在方法调用时通过 AoP 注入(inject)它。因此,我围绕我的方法的代理创建了,这是为在我的服务层中设置存储库接口(interface)代理而编写的代码。对于下面的类,您需要进行一些配置,以便可以在您的服务周围调用它。

public class RepositoryCapableInterceptor implements MethodInterceptor, ApplicationContextAware{

    private ApplicationContext applicationContext;

    /**
     *
     * @param methodInvocation method invocation passed by Spring
     * @return return value of target method.
     * @throws Throwable
     */
   @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        Object currentObj = methodInvocation.getThis();
        List<Field> toInitializeFields = fetchAllOptymyzeRepositoryChildes(currentObj);
        if (! toInitializeFields.isEmpty()) {
            RepositoryFactorySupport factory = applicationContext.getBean(RepositoryCreator.class).getRepositoryFactorySupport();
            for (Field f : toInitializeFields) {
                Object bean = factory.getRepository(f.getType());
                f.set(currentObj, bean);
                f.setAccessible(false);
            }
        }
        return methodInvocation.proceed();
    }

    private List<Field> fetchAllOptymyzeRepositoryChildes(Object currentObj) throws IllegalAccessException {
        List<Field> toInitializeFields = newArrayList();
        for (Field field : currentObj.getClass().getDeclaredFields()) {
            if(OptymyzeRepository.class.isAssignableFrom(field.getType())){
                field.setAccessible(true);
                if (field.get(currentObj) == null){
                    toInitializeFields.add(field);
                } else {
                    field.setAccessible(false);
                }
            }
        }
        return toInitializeFields;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

希望对您有所帮助。

关于java - 如何将 jpa 存储库初始化从启动时间移动到 Multi-Tenancy 环境的 session 创建时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28735837/

相关文章:

java - Spring aop 多个切入点和建议,但只有最后一个有效

java - Spring 规范和可分页

java - 无法连接到 MySQL - Glassfish 和 Hibernate

java - 在 JavaFX 中使用 WebView 会破坏 Linux 上的 UI

java - Selenium getAttribute(href) 使用 java 返回 null 值 - Salesforce 应用程序

java - 如何使用 Java 反射来调用引用变量上的方法?

java - 我有一个无法追踪的 java.lang.ClassNotFoundException 错误

java - 对象继承 - 重构问题 - 创建灵活服务的可能性

database - 我是否需要创建一个我想用 H2 预填充的表?

java - 双向关系总是逆映射?