2017-02-25 31 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> 
相關問題