我们正在使用多租户交易管理器,如上文注册日期: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;
}
}
答案 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;
}
}
目前正在使用上述代码进行测试,似乎已修复了问题。