我重新利用了現有的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)
顯然'dataSourceLookup'爲null,並且給出了配置,我猜測Hibernate已經實例化了自己的MultiTenantConnectionProviderImpl實例,而不是通過Spring注入它。 –
刪除了最後的評論,因爲我錯了,對此感到抱歉。我明白你的意思了,試圖修復它... –