发布网友 发布时间: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之前的切换。