首 页 行业热点 新车 试驾评测 养车用车 车型库

如何动态添加数据源

发布网友 发布时间:2022-04-24 08:06

我来回答

2个回答

懂视网 时间:2022-05-02 03:45

* * 加入用户数据源 */ routingDataSource.addDataSource(userid);

 

 /**
 * 根据用户创建数据源
 */
 public void addDataSource(String userid) {
 if (StringUtils.isBlank(userid))
  return;
 DbInfo dbInfo = getDbInfoService().getDbInfoByUserId(userid);
 try {
  Field targetDataSources = AbstractRoutingDataSource.class.getDeclaredField("targetDataSources");
  Field resolvedDataSources = AbstractRoutingDataSource.class.getDeclaredField("resolvedDataSources");
  targetDataSources.setAccessible(true);
  resolvedDataSources.setAccessible(true);
  Map<Object, Object> dataSources = (Map<Object, Object>) targetDataSources.get(this);
  if (dataSources.get(userInfo.getId().toString()) != null)
  return;
  Map<Object, DataSource> dataSources2 = (Map<Object, DataSource>) resolvedDataSources.get(this);
  DruidDataSource dds = new DruidDataSource();
  dds.setUrl("jdbc:mysql://" + dbInfo.getDbaddr() +
   ":" + dbInfo.getDbport() + "/" + dbInfo.getDbname() + "?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&useSSL=true");
  dds.setUsername(dbInfo.getUsername());
  dds.setPassword(dbInfo.getPwd());
  dataSources.put(userid, dds);
  dataSources2.put(userid, dds);
 } catch (NoSuchFieldException e) {
  e.printStackTrace();
 } catch (IllegalAccessException e) {
  e.printStackTrace();
 }
 }



加入了数据源,当然需要删除,可以在Session里面,销毁Session的时候删除

 /**
 * 根据用户删除数据源
 */
 public void removeDataSource(String userid) {
 if (StringUtils.isBlank(userid))
  return;
 try {
  Field targetDataSources = AbstractRoutingDataSource.class.getDeclaredField("targetDataSources");
  Field resolvedDataSources = AbstractRoutingDataSource.class.getDeclaredField("resolvedDataSources");
  targetDataSources.setAccessible(true);
  resolvedDataSources.setAccessible(true);
  Map<Object, Object> dataSources = (Map<Object, Object>) targetDataSources.get(this);
  if (dataSources.get(userInfo.getUsrno()) != null) {
  Map<Object, DataSource> dataSources2 = (Map<Object, DataSource>) resolvedDataSources.get(this);
  dataSources.remove(userid);
  dataSources2.remove(userid);
  }
 } catch (NoSuchFieldException e) {
  e.printStackTrace();
 } catch (IllegalAccessException e) {
  e.printStackTrace();
 }
 }

注解加Aop 切换数据源

注解

/**
 * Created by 为 .
 * 根据当前用户切换数据源
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SwitchDataSource {
}

Spring AOP,新版本的SpringAOP 可以很好切入,因为可以被Spring容器管理了,变相加强了SpringAop,这样就不需要使用原生Aspectj了

/**
 * Created by 为 on 2017-4-27.
 */
@Component
@Aspect
@Order(0)//配置Spring注解事务时,在事务之前切换数据源
public class SwitchDataSourceAspectj {

 //定义切点
 @Pointcut("@annotation(com.lzw.common.annotation.SwitchDataSource)")
 public void switchDataSource(){}

 @Around("switchDataSource()")
 public Object arounduserDataSource(ProceedingJoinPoint joinPoint){
 DataSourceContextHolder.user();
 try {
  return joinPoint.proceed();
 } catch (Throwable throwable) {
  throwable.printStackTrace();
 }finally {
  DataSourceContextHolder.write();
 }
 return null;
 }
}

这样可以在方法上添加注解切换数据源(注意事务与切换数据源的注解顺序),不过如果在一个方法中需要多次切换到不同数据源查询数据,会消耗很多连接数,为了更好控制数据库连接数,需要使用Spring事务

编程式Spring事务

注入TransactionManager

 @Resource
 private PlatformTransactionManager platformTransactionManager;

开始事务处理,开启事务是为了数据库连接重用,每个用户单独数据库,访问了不大,所以没有配置连接池

 //为了节省连接数,尽可能在一次切换里获取需要的数据
 DataSourceContextHolder.user();
 //TransactionTemplate 必须每次new出来,不能使用Spring单例注入,设置的数据会一直存在.
 TransactionTemplate transactionTemplate = new TransactionTemplate(platformTransactionManager);
 transactionTemplate.setPropagationBehavior(Propagation.REQUIRES_NEW.value());
 transactionTemplate.execute(new TransactionCallbackWithoutResult() {
  @Override
  public void doInTransactionWithoutResult(TransactionStatus status) {
      //数据库操作代码
  }
 });
 DataSourceContextHolder.write();

 

 

动态添加数据源,根据用户登录切换数据库.编程式Spring事务.

标签:方法   session   round   bit   aop   .exe   boolean   value   cal   

热心网友 时间:2022-05-02 00:53

现在又要实现一个新功能,就是动态添加数据源。 具体是:项目现在可以在服务器运行时动态地在数据库A,B,C(预先在项目中配置好)之间切换,并且多用户之前不会相互影响。 现在需要,在服务器运行时,手动创建一套新的数据库环境(比如D),并且要让用户在登录时,通过配置连接到这个新创建的D环境上,并且可以实现A,B,C,D之前的切换。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com