【问题标题】:Dynamically (Runtime) change Datasource credentials in Spring Mybatis在 Spring Mybatis 中动态(运行时)更改数据源凭据
【发布时间】:2014-03-05 13:01:46
【问题描述】:

我想在 Spring+MyBatis 项目中动态更改 Datasource 属性。

问题是在Spring + MyBatis集成中,我们无法在运行时动态设置数据源属性。

目前我正在使用以下代码来设置凭据:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close" p:driverClassName="${jdbc.driverClassName}"
    p:url="${jdbc.url}" p:username="${jdbc.username}"
    p:password="${jdbc.password}" />

我尝试使用 UserCredentialsDataSourceAdapter 选项在运行时更改密码,但我无法返回 dataSource 对象作为 MyBatis 用于连接

ApplicationContext context = ApplicationContextUtils.getApplicationContext();
UserCredentialsDataSourceAdapter ds = (UserCredentialsDataSourceAdapter) context.getBean("dataSource");
ds.setCredentialsForCurrentThread("test", "test");

我被困在这里,我无法使用 dataSource 元素 ds 来为 MyBatis 建立连接。请帮我解决这个问题。

【问题讨论】:

  • 没有。这对我来说不会锻炼 AbstractRoutingDataSource 用于动态路由已经定义数据源参数的数据源,但在我的情况下,我想在运行时根据登录用户动态确定用户 ID 和密码。
  • 这个问题有什么解决办法吗?

标签: spring jdbc datasource mybatis


【解决方案1】:

我猜你使用mybatis-spring

您使用UserCredentialsDataSourceAdapter 的方法不起作用,因为您正在使用连接池,因此连接在使用后不会关闭,而是返回到池中并在以后重新使用,即使您更改了用户名和密码。 要解决这个问题,只需摆脱池:

<bean id="targetDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="${jdbc.driverClassName}"/>
  <property name="url" value="${jdbc.url}"/>
</bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.UserCredentialsDataSourceAdapter">
  <property name="targetDataSource" ref="targetDataSource"/>
  <property name="username" value="${jdbc.username}"/>
  <property name="password" value="${jdbc.password}"/>
</bean>

并在 SqlSessionFactoryBean 配置中使用后面的 bean:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
</bean>

如果不使用mybatis-spring,直接使用mybatis,那么问题就在于让mybatis使用配置好的DataSource。这可以通过registering JNDI 中的dataSource 和configure mybatis 从JNDI 中获取DataSource 来完成。

【讨论】:

  • 当我使用 UserCredentialsDataSourceAdapter 时,即使没有连接池,我也无法将其传递给 mybatis。例如,在我的代码中,我从服务层调用 DAO,如下所示 private AuthDao authDao; rowsAffected = authDao.updateUserDetails(authBean);其中 AuthDao 是一个接口,它将调用查询/SP
  • 相信你即使不使用mybatis-spring也可以。我已经更新了我的答案。
  • 我正在使用 myBatis-Spring。我累了,但它不工作。它正在使用它在服务器启动时初始化的凭据。
  • 请提供mybatis和db相关的spring bean的完整配置,即datasources、sqlsessionfactory。
  • 这个问题有什么解决办法吗?
【解决方案2】:

<bean id="targetDataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${app.jdbc.driverClassName}" />
    <property name="url" value="${app.jdbc.url}" />
</bean>

<bean id="dataSource"
    class="org.springframework.jdbc.datasource.UserCredentialsDataSourceAdapter">
    <property name="targetDataSource" ref="targetDataSource" />
    <property name="username" value="#{app.jdbc.username}" />
    <property name="password" value="#{app.jdbc.password}" />
</bean>

<!-- Declare a transaction manager for Encounter Navigator Authenticator -->
<!-- Enable annotation style of managing transactions -->
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

<!-- define the SqlSessionFactory for Encounter Navigator Authenticator, 
    notice that configLocation is not needed when you use MapperFactoryBean -->
<bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
    name="sqlSessionFactory">
    <property name="dataSource" ref="dataSource" />
    <property name="mapperLocations"
        value="file:C:/Program Files/Apache Software Foundation/Tomcat 7.0/config/app_user/*.xml" />
    <property name="configLocation" value="classpath:sqlmap-config.xml" />
</bean>

<!-- scan for MAPPERS and let them be auto-wired - For Encounter Navigator 
    Authenticator -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage"
        value="com.upmc.health.encounternavigator.dao.authentication" />
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>

【讨论】:

    【解决方案3】:
    UserCredentialsDataSourceAdapter ds = (UserCredentialsDataSourceAdapter) applicationContext.getBean("dataSource");
    ds.removeCredentialsFromCurrentThread();
    ds.setCredentialsForCurrentThread("test", "test");
    ds.setUsername("test");
    ds.setPassword("test");
    ds.setTargetDataSource(ds);
    ds.afterPropertiesSet();
    

    authDao.getDetails(); //这会调用一个接口并执行xml文件中的查询

    【讨论】:

      猜你喜欢
      • 2022-06-12
      • 1970-01-01
      • 1970-01-01
      • 2018-01-25
      • 1970-01-01
      • 2012-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多