Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在多租户连接提供程序中选择数据源时出现NullPointerException_Java_Spring_Hibernate_Multi Tenant - Fatal编程技术网

Java 在多租户连接提供程序中选择数据源时出现NullPointerException

Java 在多租户连接提供程序中选择数据源时出现NullPointerException,java,spring,hibernate,multi-tenant,Java,Spring,Hibernate,Multi Tenant,我重新调整了现有hibernate spring项目的用途,升级到hibernate 4和spring 4,并使用多租户添加了多个数据源。应用程序启动正常,正在使用MultiTenantDataSourceLookup类读入数据源。设置新租户时,租户已解析,但随后我在MultiTenantConnectionProviderImpl的第41行获得nullpointerexception(请参阅第行的注释)。如果有帮助的话,我也在使用generichbernatedao。我可以根据要求发布代码。我

我重新调整了现有hibernate spring项目的用途,升级到hibernate 4和spring 4,并使用多租户添加了多个数据源。应用程序启动正常,正在使用MultiTenantDataSourceLookup类读入数据源。设置新租户时,租户已解析,但随后我在MultiTenantConnectionProviderImpl的第41行获得nullpointerexception(请参阅第行的注释)。如果有帮助的话,我也在使用generichbernatedao。我可以根据要求发布代码。我刚接触spring,所以问题可能很简单。但是,如果需要更多的代码来帮助我,我会很乐意在自己解决问题和研究问题时分享更多。任何帮助都将不胜感激。谢谢以下是完整的堆栈跟踪:


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;
    }   
}
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;
    }
}

CurrentTenantIdentifierResolverImpl.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;
    }   
}
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>

我将hibernate属性更改为以下内容,现在一切正常:

<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>


显然
dataSourceLookup
为空,根据给定的配置,我猜Hibernate已经实例化了自己的
MultiTenantConnectionProviderImpl
实例,而不是通过Spring注入它。删除了最后一条注释,因为我错了,对此表示抱歉。我明白你在说什么,试图解决它。。。