在Hibernate多租户应用程序中,启动时不会对数据源进行查找

4
我目前正在使用Spring和Hibernate开发一个多租户应用程序,使用独立的数据库。我希望即使其中一个数据源不可访问(出现问题),我的应用程序仍然能够正常工作,以便其他租户仍然可以访问他们的数据。因此,我不希望我的应用程序在部署时检查数据源。我尝试告诉它在启动时不要查找数据源:
applicationContext-datasources.xml :

<!-- data source 1 -->
<jee:jndi-lookup id="ds1" jndi-name="jdbc/ds1" resource-ref="true" lookup-on-startup="false" expected-type="javax.sql.DataSource" />

<!-- data source 2 -->
<jee:jndi-lookup id="ds2" jndi-name="jdbc/ds2" resource-ref="true" lookup-on-startup="false" expected-type="javax.sql.DataSource" />

但是我得到了以下异常堆栈:

11:24:10,192 INFO  [STDOUT] 2014-11-28 11:24:10,189 - ERROR [main (ContextLoader.java:307) - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myDAO': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in file [applicationContext.xml]: Invocation of init method failed; nested exception is org.springframework.jndi.JndiLookupFailureException: JndiObjectTargetSource failed to obtain new target object; nested exception is javax.naming.NameNotFoundException: jdbc not bound
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in file [applicationContext.xml]: Invocation of init method failed; nested exception is org.springframework.jndi.JndiLookupFailureException: JndiObjectTargetSource failed to obtain new target object; nested exception is javax.naming.NameNotFoundException: jdbc not bound
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:342)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
...
Caused by: org.springframework.jndi.JndiLookupFailureException: JndiObjectTargetSource failed to obtain new target object; nested exception is javax.naming.NameNotFoundException: jdbc not bound
at org.springframework.jndi.JndiObjectTargetSource.getTarget(JndiObjectTargetSource.java:139)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:182)
at $Proxy54.getConnection(Unknown Source)
at com.example.MultiTenantConnectionProviderImpl.getConnection(MultiTenantConnectionProviderImpl.java:45)
at com.example.MultiTenantConnectionProviderImpl.getAnyConnection(MultiTenantConnectionProviderImpl.java:31)
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl$MultiTenantConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcServicesImpl.java:302)
...
Caused by: javax.naming.NameNotFoundException: jdbc not bound
at org.jnp.server.NamingServer.getBinding(NamingServer.java:529)
at org.jnp.server.NamingServer.getBinding(NamingServer.java:537)
at org.jnp.server.NamingServer.getObject(NamingServer.java:543)
at org.jnp.server.NamingServer.lookup(NamingServer.java:267)
at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:625)
at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:587)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:154)
at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:178)
at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:104)
at org.springframework.jndi.JndiObjectLocator.lookup(JndiObjectLocator.java:105)
at org.springframework.jndi.JndiObjectTargetSource.getTarget(JndiObjectTargetSource.java:132)
...

如果我在applicationContext-datasources.xml中将lookup-on-startup设置为true,那么它可以完美地工作。但是我知道,即使其他租户可以访问数据源,如果其中一个数据源不可用,它也无法工作。感谢您的帮助。
1个回答

0

我找到了实现我的目标的方法,但解决方案并不完美。

当我声明我的类MultiTenantConnectionProviderImpl时,在getAnyConnection()方法中,我提供了一个来自默认数据库的连接,该数据库由所有租户共享:

public class MultiTenantConnectionProviderImpl implements MultiTenantConnectionProvider, Stoppable {

    @Override
    public Connection getAnyConnection() throws SQLException {
        return defaultDataSource.getConnection();
    }
    ...
}

我让其他方法确定当前租户。

然后,在applicationContext-datasources.xml中,我可以按照自己的意愿声明所有其他数据源:

applicationContext-datasources.xml :

<!-- default data source -->
<jee:jndi-lookup id="defaultDatasource" jndi-name="jdbc/defaultDatasource" resource-ref="true" lookup-on-startup="true" expected-type="javax.sql.DataSource" />

<!-- data source 1 -->
<jee:jndi-lookup id="ds1" jndi-name="jdbc/ds1" resource-ref="true" lookup-on-startup="false" expected-type="javax.sql.DataSource" />

<!-- data source 2 -->
<jee:jndi-lookup id="ds2" jndi-name="jdbc/ds2" resource-ref="true" lookup-on-startup="false" expected-type="javax.sql.DataSource" />

这样可以运行,但需要共享数据库。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接