2017-02-25 35 views
0

我重新利用了现有的hibernate-spring项目并升级到Hibernate 4和Spring 4,并使用多租户添加了多个数据源。应用程序启动正常,数据源正在使用MultiTenantDataSourceLookup类读入。在设置新租户时,租户已解决,但是我在MultiTenantConnectionProviderImpl的第41行获得了nullpointerexception(请参阅行注释)。如果有帮助,我也使用GenericHibernateDAO。我可以通过请求发布该代码。我是新来的,所以问题可能非常简单。然而,如果需要更多的代码来帮助我,我会很乐意分享更多,因为我自己排查和研究问题。任何帮助将不胜感激。谢谢。以下是完整的堆栈跟踪:http://pastebin.com/LjyhTwvY在MultiTenant连接提供程序中选择DataSource时出现NullPointerException


MultiTenantConnectionProviderImpl.java

public class MultiTenantConnectionProviderImpl extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl 
{ 

    @Autowired 
    private DataSource defaultDataSource; 
    @Autowired 
    private DataSourceLookup dataSourceLookup; 

    /** 
    * Select datasources in situations where not tenantId is used (e.g. startup processing). 
    */ 
    @Override 
    protected DataSource selectAnyDataSource() { 
     return defaultDataSource; 
    } 

    /** 
    * Obtains a DataSource based on tenantId 
    */ 
    @Override 
    protected DataSource selectDataSource(String tenantIdentifier) { 
     //Below is line 41 where the nullpointerexeption is occurring 
     DataSource ds = dataSourceLookup.getDataSource(tenantIdentifier); 
     return ds; 
    } 
} 

CurrentTenantIdentifierResolverImpl.java

public class CurrentTenantIdentifierResolverImpl implements CurrentTenantIdentifierResolver { 

    private static final String KEY_TENANTID_SESSION = "hibernate.tenant_identifier_resolver"; 
    private static final String DEFAULT_TENANTID = "customer1"; 


    public String resolveCurrentTenantIdentifier() { 

     String tenant = resolveTenantByHttpSession();  
     System.out.println("Tenant resolved: " + tenant); 
     return tenant; 
    } 


    /** 
    * Get tenantId in the session attribute KEY_TENANTID_SESSION 
    * @return TenantId on KEY_TENANTID_SESSION 
    */ 
    public String resolveTenantByHttpSession() 
    { 
     ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); 
     //If session attribute exists returns tenantId saved on the session 
     if(attr != null){ 
      HttpSession session = attr.getRequest().getSession(false); // true == allow create 
      if(session != null){ 
       String tenant = (String) session.getAttribute(KEY_TENANTID_SESSION); 
       if(tenant != null){ 
        return tenant; 
       } 
      } 
     } 
     //otherwise return default tenant 
     return DEFAULT_TENANTID; 
    } 


    public boolean validateExistingCurrentSessions() { 
     return true; 
    } 
} 

的context.xml

<context:annotation-config /> 

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /> 

<bean id="multitenancyConnectionProvider" 
    class="com.github.elizabetht.util.MultiTenantConnectionProviderImpl"/> 
<bean id="dataSourceLookup" 
    class="com.github.elizabetht.util.MultiTenantDataSourceLookup"/> 
<bean id="tenantResolver" 
    class="com.github.elizabetht.util.CurrentTenantIdentifierResolverImpl"/> 


<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 

    <property name="packagesToScan"> 
     <list> 
      <value>com.github.elizabetht.model</value> 
     </list> 
    </property> 

    <property name="hibernateProperties"> 
     <props>   
     <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop> 
     <prop key="hibernate.jdbc.lob.non_contextual_creation">true</prop> 
     <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
     <prop key="hibernate.hbm2ddl.auto">create</prop> 
     <prop key="hibernate.show_sql">true</prop> 
     <prop key="hibernate.multiTenancy">DATABASE</prop> 
     <prop key="hibernate.multi_tenant_connection_provider">com.github.elizabetht.util.MultiTenantConnectionProviderImpl</prop> 
     <prop key="hibernate.tenant_identifier_resolver">com.github.elizabetht.util.CurrentTenantIdentifierResolverImpl</prop> 
     </props> 
    </property> 
</bean> 

<bean id="defaultDataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close"> 
    <property name="driverClass" value="com.mysql.jdbc.Driver" /> 
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/studentEnrollment" /> 
    <property name="username" value="springy" /> 
    <property name="password" value="pass" /> 
</bean> 

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
    <property name="autodetectDataSource" value="false"/> 
</bean> 


输出

Tenant resolved: customer1 

Feb 25, 2017 1:34:31 PM org.apache.catalina.core.StandardWrapperValve invoke 
SEVERE: Servlet.service() for servlet [studentHibernateServlet] in context with path [/StudentEnrollmentWithSpring] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause 
java.lang.NullPointerException 
at com.github.elizabetht.util.MultiTenantConnectionProviderImpl.selectDataSource(MultiTenantConnectionProviderImpl.java:41) 
at org.hibernate.engine.jdbc.connections.spi.AbstractDataSourceBasedMultiTenantConnectionProviderImpl.getConnection(AbstractDataSourceBasedMultiTenantConnectionProviderImpl.java:52) 
at org.hibernate.internal.AbstractSessionImpl$ContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:423) 
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:228) 
+0

显然'dataSourceLookup'为null,并且给出了配置,我猜测Hibernate已经实例化了自己的MultiTenantConnectionProviderImpl实例,而不是通过Spring注入它。 –

+0

删除了最后的评论,因为我错了,对此感到抱歉。我明白你的意思了,试图修复它... –

回答

0

我改变了我的休眠特性以下,一切工作现在:

<property name="hibernateProperties"> 
    <map> 
     <entry key="hibernate.multi_tenant_connection_provider" value-ref="multitenancyConnectionProvider"/> 
     <entry key="hibernate.tenant_identifier_resolver" value-ref="tenantResolver"/>        
     <entry key="hibernate.multiTenancy" value="DATABASE"/> 
    </map> 
</property> 
相关问题