我正在使用 Struts2、Spring 和 Hibernate 开发一个多数据源 Web 门户。我在将用户凭据设置为我的一个数据源时遇到问题,这些凭据在应用程序启动时不可用,但在用户登录时不可用。它适用于第一个门户用户,但对每个后续用户都失败。
对于每个数据源,都会创建一个会话工厂,它通过 spring 配置获取底层数据源集。
我的四个数据源中的三个通过配置设置了它们的数据库登录凭据,但其中一个必须使用门户用户的凭据。请注意,我的 bean 在会话范围内。
这是我的数据源配置:
<!-- data source with credentials from configuration -->
<bean id="dataSource1" class="org.springframework.jdbc.datasource.DriverManagerDataSource" scope="session">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- data source that authenticates with user credentials from login. -->
<bean id="dataSource2" class="org.springframework.jdbc.datasource.DriverManagerDataSource" scope="session">
<property name="driverClassName" value="${ds2.jdbc.driverClassName}" />
<property name="url" value="${ds2.jdbc.url}" />
</bean>
这是我的会话工厂配置:
<bean id="sessionFactory1" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" scope="session">
<property name="dataSource">
<ref bean="dataSource1" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
...
</props>
</property>
<property name="mappingResources">
<list>
<value>hibernate/AnotherDTO.hbm.xml</value>
...
</list>
</property>
</bean>
<bean id="sessionFactory2" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" scope="session">
<property name="dataSource">
<ref bean="dataSource2" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
...
</props>
</property>
<property name="mappingResources">
<list>
<value>hibernate/MyDTO.hbm.xml</value>
...
</list>
</property>
</bean>
门户用户的用户名和密码只有在成功登录门户后才可用,因此必须以编程方式将它们设置为数据源之一 (dataSource2)。
我通过让 Spring 将数据源插入到我的登录操作 (Struts2) 中来实现这一点,然后在每次登录后使用提供的 setter 方法在数据源处设置用户名和密码。
@Qualifier("dataSource2")
private DriverManagerDataSource dataSource2;
private void postAuthenticate() {
dataSource2.setUsername(user);
dataSource2.setPassword(password);
}
我的 DAO 将会话工厂插入构造函数中,并将其传递给 HibernateDaoSupport(是的,我使用 HibernateTemplate,请不要讨论他的观点 ;-)):
public class MyDAO extends HibernateDaoSupport {
@Autowired
public MyDAO(@Qualifier("sessionFactory2") SessionFactory pSessionFactory) {
setSessionFactory(pSessionFactory);
}
...
}
现在,这对于第一个使用门户的用户来说效果很好。在门户的起始页上,显示了来自使用 dataSource2 的 DAO 的项目列表。但是,每个登录到门户的以下用户都不会从我的 dataSource2 中获得任何结果。不会引发异常,也不会出现日志消息,因为存在与数据库的有效连接,仅使用其他人的凭据(因此不会为第二个用户返回合适的结果)。
我的假设是,Hibernate 或 Spring 不会以某种方式从前一个用户的会话工厂丢弃旧连接并继续使用它,或者忽略我在新数据源中设置的新凭据。
谁能为我的问题提供一些见解或有用的提示(或解决方案!)?我想知道使用具有在应用程序启动时不可用但在用户登录时不可用的用户凭据的数据源是否真的那么难,并且没有可用的简单通用方法(我在网络上的任何地方都没有找到合适的解决方案)。
非常感谢。