使用Spring JpaTransactionManager时,Eclipse Link中未处理并发

时间:2017-05-24 09:11:22

标签: spring jpa eclipselink multi-tenant

我们正在使用多租户交易管理器,如上文注册日期:2014年11月所述。我们使用的是Spring Data,我们也根据用户ID和密码识别租户,即我们不了解租户。该应用程序工作正常。我们使用spring security和基本身份验证。并通过Rest API公开应用程序。

当并发的不同租户同时使用事务管理器时,会出现问题。我们使用TenantResolver类来查找租户

我们还有其他2个消息流,每分钟有大约40条消息和10条消息,它们使用连接管理器查找租户并根据该消息执行事务。

这里的日志:

  

MultiTenantJpaTransactionManager.createEntityManagerForTransaction() - >   ACTUAL_TENANT:vce 07:51:05,720 INFO   [xxx.integration.jms.VehicleRepositoryListener]   (vrMessageListenerContainer-1)[]   VehicleRepositoryListener.onMessage() - >处理成功   在VehicleRepositoryListener 07:51:05,768中完成错误   [xxx.integration.services.utils.TenantUtils]   (vrMessageListenerContainer-1)[] TenantUtils.setTenantByProductClass    - >设置租户org.springframework.orm.jpa.JpaSystemException时出错:异常   [EclipseLink-28013](Eclipse持久性服务 -   2.6.0.v20150309-bf26070):org.eclipse.persistence.exceptions.EntityManagerSetupException   异常描述:无法部署PersistenceUnit [default]   无效状态[DeployFailed]。内部异常:   javax.persistence.PersistenceException:异常[EclipseLink-28019]   (Eclipse Persistence Services - 2.6.0.v20150309-bf26070):   org.eclipse.persistence.exceptions.EntityManagerSetupException   异常说明:PersistenceUnit [default]的部署失败。   关闭此PersistenceUnit的所有工厂。内部异常:   javax.persistence.PersistenceException:异常[EclipseLink-28009]   (Eclipse Persistence Services - 2.6.0.v20150309-bf26070):   org.eclipse.persistence.exceptions.EntityManagerSetupException   异常描述:尝试重新部署名为的会话   /文件中:/ opt / JBOSS64 /模块/系统/层/基层/组织/ JBoss的/ AS / EJB3 /主/定时器/ _default   没有关闭它。嵌套异常是   javax.persistence.PersistenceException:Exception [EclipseLink-28013]   (Eclipse Persistence Services - 2.6.0.v20150309-bf26070):   org.eclipse.persistence.exceptions.EntityManagerSetupException   异常描述:无法部署PersistenceUnit [default]   无效状态[DeployFailed]。内部异常:   javax.persistence.PersistenceException:异常[EclipseLink-28019]   (Eclipse Persistence Services - 2.6.0.v20150309-bf26070):   org.eclipse.persistence.exceptions.EntityManagerSetupException   异常说明:PersistenceUnit [default]的部署失败。   关闭此PersistenceUnit的所有工厂。内部异常:   javax.persistence.PersistenceException:异常[EclipseLink-28009]   (Eclipse Persistence Services - 2.6.0.v20150309-bf26070):   org.eclipse.persistence.exceptions.EntityManagerSetupException   异常描述:尝试重新部署名为的会话   /文件中:/ opt / JBOSS64 /模块/系统/层/基层/组织/ JBoss的/ AS / EJB3 /主/定时器/ _default   没有关闭它。 07:51:05,774 INFO   [xxxintegration.services.XXXUpdateRequestProcessServiceImpl]   (xxxMessageListenerContainer-1)[]返回   XXXUpdateRequestProcessServiceImpl.login()07:51:05,775 INFO   [xxx.integration.services.XXXUpdateRequestProcessServiceImpl]   (xxxMessageListenerContainer-1)[]   XXXUpdateRequestProcessServiceImpl.getUpdateTechToolResponseDTOs() - >   令牌服务:b3b00ab6-5c36-45af-8ec2-0b6f1710e888 07:51:05,777   INFO [xxx.integration.services.VehicleRepositoryService]   (vrMessageListenerContainer-1)[]   VehicleRepositoryService.parseVehicleRepositoryUpdate() - >租客是   null 07:51:05,780 INFO [xxx.integration.jms.VehicleRepositoryListener]   (vrMessageListenerContainer-1)[]   VehicleRepositoryListener.onMessage() - >处理成功   在VehicleRepositoryListener 07:51:06,138 INFO中完成   [xxx.application.VehicleActivationService](http- / 0.0.0.0:16780-71)[]   Inside VehicleActivationService.checkActivation()07:51:06,141 INFO   [xxx.application.VehicleActivationService](http- / 0.0.0.0:16780-71)[]   Inside VehicleActivationService.getTenant()07:51:06,145 ERROR   [xxx.integration.rest.UpdateTechTool](http- / 0.0.0.0:16780-71)[]   检查激活方法中的异常:无法打开JPA   用于交易的EntityManager;嵌套异常是   javax.persistence.PersistenceException:Exception [EclipseLink-28013]   (Eclipse Persistence Services - 2.6.0.v20150309-bf26070):   org.eclipse.persistence.exceptions.EntityManagerSetupException   异常描述:无法部署PersistenceUnit [default]   无效状态[DeployFailed]。内部异常:   javax.persistence.PersistenceException:异常[EclipseLink-28019]   (Eclipse Persistence Services - 2.6.0.v20150309-bf26070):   org.eclipse.persistence.exceptions.EntityManagerSetupException   异常说明:PersistenceUnit [default]的部署失败。   关闭此PersistenceUnit的所有工厂。内部异常:   javax.persistence.PersistenceException:异常[EclipseLink-28009]   (Eclipse Persistence Services - 2.6.0.v20150309-bf26070):   org.eclipse.persistence.exceptions.EntityManagerSetupException   异常描述:尝试重新部署名为的会话   /文件中:/ opt / JBOSS64 /模块/系统/层/基层/组织/ JBoss的/ AS / EJB3 /主/定时器/ _default   没有关闭它。 07:51:06,148信息   [xxx.application.XXXUpdateTechToolDTOService](http- / 0.0.0.0:16780-71)   []里面的UpdateTechToolDTOService.update()07:51:06,154错误   [xxx.application.XXXUpdateTechToolDTOService](http- / 0.0.0.0:16780-71)   [] XXXUpdateTechToolDTOService.update() - >打电话时除外   update:java.lang.NullPointerException 07:51:06,166 INFO   [xxx.integration.services.UpdateRequestProcessServiceImpl]   (MessageListenerContainer-1)[]里面   UpdateRequestProcessServiceImpl.createResponse()07:51:06,883 INFO   [stdout](Finalizer)[] [EL Info]:连接:2017-04-17   07:51:06.882 - 的ServerSession(1485077057) - /文件中:/ opt / JBOSS64 /模块/系统/层/基层/组织/ JBoss的/ AS / EJB3 /主/定时器/ _default   退出成功07:51:06,885 INF

处理并发问题的任何帮助或方法。

类似于: EclipseLink - Error: Attempted to redeploy a session without closing it

使用的MultiTenantJpaTransactionManager类是:

公共类MultiTenantJpaTransactionManager扩展了JpaTransactionManager {

TenantResolver<Tenant> tenantResolver; 
SchemaProvider schemaProvider; 
@Autowired
public void setTenantResolver(TenantResolver<Tenant> tenantResolver) {
    this.tenantResolver = tenantResolver;
}

@Autowired(required = false)
public void setSchemaProvider(SchemaProvider schemaProvider) {
    this.schemaProvider = schemaProvider;
}

@Override
protected synchronized javax.persistence.EntityManager createEntityManagerForTransaction() {
    boolean refreshed = false;
    EntityManager em = super.createEntityManagerForTransaction();
    try {
        LOGGER.info("Entering createEntityManagerforTransaction()");
        if (schemaProvider != null) {
            TenantSessionCustomizer.setSchemaName(schemaProvider.getSchema());
        }
        ServerSession ss = ((EntityManagerImpl) em.getDelegate()).getServerSession();
        Map sessionProp = ss.getProperties();
        String actualTenant = (String) sessionProp.get(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT);
        LOGGER.info("MultiTenantJpaTransactionManager.createEntityManagerForTransaction()-> ACTUAL_TENANT : " + actualTenant);

        if (tenantResolver != null && tenantResolver.getCurrentTenant() != null) {
            LOGGER.info("MultiTenantJpaTransactionManager.createEntityManagerForTransaction()-> CURRENT_TENANT : " + tenantResolver.getCurrentTenant());
            if ((actualTenant == null) || (actualTenant != null && !actualTenant.equals(tenantResolver.getCurrentTenant().getHandle()))) {
                sessionProp.put(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, tenantResolver.getCurrentTenant().getHandle());
                sessionProp.put(PersistenceUnitProperties.SESSION_CUSTOMIZER, TenantSessionCustomizer.class.getName());
                MetadataRefreshListener mrl = ((EntityManagerImpl) em.getDelegate()).getServerSession().getRefreshMetadataListener();
                if (mrl != null) {
                    Map<String, Object> prop = new HashMap<String, Object>();
                    mrl.triggerMetadataRefresh(prop);
                    refreshed = true;
                    LOGGER.info("createEntityManagerforTransaction()---->Metadata refreshed");
                }
            }
        }
    } catch (Exception ex) {
        LOGGER.error("MultiTenantJpaTransactionManager.createEntityManagerForTransaction()-> Exception while creating EntityManagerForTransaction " + ex.getMessage());
    }
    return refreshed ? super.createEntityManagerForTransaction() : em;
}

}

2 个答案:

答案 0 :(得分:0)

关注https://www.eclipse.org/eclipselink/documentation/2.5/solutions/multitenancy002.htm

这可能有效:

@Override
protected synchronized javax.persistence.EntityManager createEntityManagerForTransaction() {
    boolean refreshed = false;
    EntityManagerFactory emf = getEntityManagerFactory();
    EntityManager em = null;
    try {
        if (schemaProvider != null) {
            TenantSessionCustomizer.setSchemaName(schemaProvider.getSchema());
        }
        Map tenantProp = new HashMap();

        if (tenantResolver != null && tenantResolver.getCurrentTenant() != null) {
           tenantProp.put(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, tenantResolver.getCurrentTenant().getHandle());

             em = emf.createEntityManager(tenantProp);
        }
    } catch (Exception ex) {
        LOGGER.error("MultiTenantJpaTransactionManager.createEntityManagerForTransaction()-> Exception while creating EntityManagerForTransaction " + ex.getMessage());
    }
    return em;
}

答案 1 :(得分:0)

公共类MultiTenantJpaTransactionManager扩展JpaTransactionManager {     private static final Logger LOGGER = LoggerFactory.getLogger(MultiTenantJpaTransactionManager.class);

TenantResolver<Tenant> tenantResolver; 
SchemaProvider schemaProvider;

@Autowired
public void setTenantResolver(TenantResolver<Tenant> tenantResolver) {
    this.tenantResolver = tenantResolver;
}

@Autowired(required = false)
public void setSchemaProvider(SchemaProvider schemaProvider) {
    this.schemaProvider = schemaProvider;
}

@Override
protected synchronized javax.persistence.EntityManager createEntityManagerForTransaction() {
    boolean refreshed = false;
    EntityManagerFactory emf = getEntityManagerFactory();
    EntityManager em = super.createEntityManagerForTransaction();
    try {
        LOGGER.info("Entering createEntityManagerforTransaction()");
        if (schemaProvider != null) {
            TenantSessionCustomizer.setSchemaName(schemaProvider.getSchema());
        }
        ServerSession ss = ((EntityManagerImpl) em.getDelegate()).getServerSession();
        Map sessionProp = ss.getProperties();

        if (tenantResolver != null && tenantResolver.getCurrentTenant() != null) {
            sessionProp.put(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, tenantResolver.getCurrentTenant().getHandle());

            em = emf.createEntityManager(sessionProp);
        }
    } catch (Exception ex) {
        LOGGER.error("MultiTenantJpaTransactionManager.createEntityManagerForTransaction()-> Exception while creating EntityManagerForTransaction " + ex.getMessage());
    }
    return em;
}

}

目前正在使用上述代码进行测试,似乎已修复了问题。