2012-10-03 40 views
1

我正面临使用Hibernate 4.1.7和EJB 3.1使用GlassFish 3.1.2作为Java EE容器实现多租户应用程序的问题 目前有一类实现org.hibernate.context.spi.CurrentTenantIdentifierResolver它标识记录在房客撷取登录的用户与此代码:多租户解决错误的租户标识符EJB + JPA + HIBERNATE

@Override 
public String resolveCurrentTenantIdentifier() { 
    try { 
     SessionContext context = ServiceLocator.locate(SessionEjbContext.class).getSessionContext(); 

     String userName = context.getCallerPrincipal().getName(); 

     AppLogger.info("current tenant identifier [" + userName + "]"); 

     return userName; 
    } catch (Throwable e) { 
     AppLogger.info("erro lookup"); 
    } 

    return "default"; 
} 

的SessionContext.class这样

@Stateful 
@SessionScoped 
public class SessionEjbContext { 

    @Resource 
    private SessionContext sessionContext; 

    public SessionContext getSessionContext() { 
     return sessionContext; 
    } 
} 

的ID被实现为然后提供给扩展org.hibernate.service.jdbc.connections.spi.AbstractMultiTenantConnectionProvider的类,该类实现了方法ConnectionProvider selectConnectionProvider(String tenantIdentifier),并且必须返回一个要使用的c3p0 ConnectionProvider对象。

真正的问题是这样的: 当用户user1对系统进行身份验证时,db连接已解析正常。 但是,当user2进行身份验证时,方法ConnectionProvider selectConnectionProvider(String tenantIdentifier)接收的参数为user1,而不是user2,导致我们选择与user1相同的数据库。

EntityManager是用PersistenceContextType.EXTENDED注释实现的,是导致问题的原因吗?也许它正在重复使用关于第一个用户的信息!

回答

0

根据各种帖子,有状态bean的JNDI查找可以创建bean的新实例。相反,对于resolveCurrentTenantIdentifier()的调用,将返回相同的bean。请检查服务定位器和JNDI查找方法。 这是JNDI库缓存对象实例的常见行为。由于您已经调用了与user1相对应的SessionEjbContext的JNDI查找,因此可能已被缓存,并且将被所有后续调用返回。