Spring多数据源解决方案
Figure 2 多数据源的选择逻辑渗透至客户端
解决方案
Figure 3 采用Proxy模式来封转数据源选择逻辑
通过采用Proxy模式我们在方案实现中实现一个虚拟的数据源.并且通过它来封装数据源选择逻辑,这样就可以有效地将数据源选择逻辑从Client中分离出来.Client提供选择所需的上下文(因为这是Client所知道的),有虚拟的DataSource根据Client提供的上下文来实现数据源的选择.Spring2.x的版本中提供了实现这种方式的基本框架.虚拟的DataSource仅需要继承AbstractRoutingDataSource实现determineCurrentLookupKey()在其中封装数据源选择逻辑.
实例:
public class DynamicDataSource extends AbstractRoutingDataSource{
static Logger log=Logger.getLogger("DynamicDataSource");
@Override
protected Object determineCurrentLookupKey(){
String userId=(String)DbContextHolder.getContext();
Integer dataSourceId=getDataSourceIdByUserId(userId);
return dataSourceId;
}
}
实例中通过UserId来决定数据存放在哪个数据库中。
配置文件示例:
<bean id="dataSource" class="com.bitfone.smartdm.datasource.DynamicDataSource"> <property name="targetDataSources"> <map key-type="java.lang.Integer"> <entry key="0" value-ref="dataSource0"/> <entry key="1" value-ref="dataSource1"/> <entry key="2" value-ref="dataSource2"/> </map> </property> <property name="defaultTargetDataSource" ref="dataSource0"/> </bean> <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation" value="classpath:com/bitfone/smartdm/dao/sqlmap/sql-map-config.xml"/> <property name="dataSource" ref="dataSource"/> </bean> <bean id="UserInfoDAO" class="com.bitfone.smartdm.dao.impl.UserInfoDAO"> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> |
下面是个人在项目中用过的配置方法(以后公布):
程序中的控制代码
public class DbContextHolder{
private static final ThreadLocal contextHolder = new ThreadLocal();
public static void setDbType(String dbType)
{
contextHolder.set(dbType);
}
public static String getDbType()
{
String str=(String) contextHolder.get();
if(null==str || "".equals(str))
str="1";
return str;
}
public static void clearDbType()
{
contextHolder.remove();
}
}
在程序中通过设置DbContextHolder.setDbType(String dbType);来控制数据库的选取,其中key配置目标数据源的键值.
本文通过实例介绍了MySQL中的group_concat函数的使用方法,比如select group_concat(name) 。
MySQL中group_concat函数
完整的语法如下:
group_concat([DISTINCT] 要连接的字段 [Order BY ASC/DESC 排序字段] [Separator '分隔符'])
基本查询
mysql> select * from aa;
+------+------+
| id| name |
+------+------+
|1 | 10|
|1 | 20|
|1 | 20|
|2 | 20|
|3 | 200 |
|3 | 500 |
+------+------+
6 rows in set (0.00 sec)
以id分组,把name字段的值打印在一行,逗号分隔(默认)
mysql> select id,group_concat(name) from aa group by id;
+------+--------------------+
| id| group_concat(name) |
+------+--------------------+
|1 | 10,20,20|
|2 | 20 |
|3 | 200,500|
+------+--------------------+
3 rows in set (0.00 sec)
以id分组,把name字段的值打印在一行,分号分隔
mysql> select id,group_concat(name separator ';') from aa group by id;
+------+----------------------------------+
| id| group_concat(name separator ';') |
+------+----------------------------------+
|1 | 10;20;20 |
|2 | 20|
|3 | 200;500 |
+------+----------------------------------+
3 rows in set (0.00 sec)
以id分组,把去冗余的name字段的值打印在一行,
逗号分隔
mysql> select id,group_concat(distinct name) from aa group by id;
+------+-----------------------------+
| id| group_concat(distinct name) |
+------+-----------------------------+
|1 | 10,20|
|2 | 20 |
|3 | 200,500 |
+------+-----------------------------+
3 rows in set (0.00 sec)
以id分组,把name字段的值打印在一行,逗号分隔,以name排倒序
mysql> select id,group_concat(name order by name desc) from aa group by id;
+------+---------------------------------------+
| id| group_concat(name order by name desc) |
+------+---------------------------------------+
|1 | 20,20,10 |
|2 | 20|
|3 | 500,200|
+------+---------------------------------------+
3 rows in set (0.00 sec)
本人在做用户有哪些角色动态显示是用到.可以提高代码简洁性与程序的效率,不用对比用户角色关联表与用户角色与用户表.
JavaScript 动态实现树形菜单(使用dtree控件)
@author Bob 2012/08/09
动态生成树型菜单 数据库脚本:
use master
go if exists (select * from sysdatabases where name = 'tree') drop database tree go create database tree on ( Name = 'tree_data', --主数据文件的逻辑名称 FileName = 'D:/tree_data.mdf', --数据文件的物理名称 Size = 5Mb, -- 主数据文件的初始大小 FileGrowth = 20% --主数据文件增长率 ) log on ( Name = 'tree_log', FileName = 'd:/tree_log.ldf', Size = 3Mb, FileGrowth = 10% ) go if exists (select * from sysobjects where name = 'dtree') drop table dtree go use tree go /*--- 创建节点表 ---*/ create table dtree ( id varchar(20) , --节点编号 pid varchar(20) , --父节点 [name] varchar(20), --节点名称 url varchar(20), --连接地址 title varchar(20), --节点描述 target varchar(20), --Target icon varchar(20), --图标 iconOpen varchar(20), --展开状态下的图标路径 [open] varchar(20) --是否展开 ) /*--- 初始化测试数据 ---*/ insert into dtree values('0','-1','T16班','index.jsp','blank','','','','') insert into dtree values('1','0','教师','index.jsp','blank','','','','') insert into dtree values('2','0','班干部','index.jsp','blank','','','','') insert into dtree values('3','0','组长','index.jsp','blank','','','','') insert into dtree values('4','0','学员','index.jsp','blank','','','','') insert into dtree values('5','1','班主任','index.jsp','blank','','','','') insert into dtree values('6','1','教员','index.jsp','blank','','','','') insert into dtree values('7','2','班长','index.jsp','blank','','','','') insert into dtree values('8','2','学委','index.jsp','blank','','','','') insert into dtree values('9','4','学员1','index.jsp','blank','','','','') insert into dtree values('10','4','学员2','index.jsp','blank','','','','') insert into dtree values('11','4','学员3','index.jsp','blank','','','','') insert into dtree values('12','4','学员4','index.jsp','blank','','','','') insert into dtree values('13','4','学员5','index.jsp','blank','','','','') insert into dtree values('14','4','学员6','index.jsp','blank','','','','') insert into dtree values('15','4','学员7','index.jsp','blank','','','','') insert into dtree values('16','4','学员8','index.jsp','blank','','','','') insert into dtree values('17','4','学员9','index.jsp','blank','','','','') insert into dtree values('18','4','学员10','index.jsp','blank','','','','') insert into dtree values('19','4','学员11','index.jsp','blank','','','','') insert into dtree values('20','4','学员12','index.jsp','blank','','','','') insert into dtree values('21','4','学员13','index.jsp','blank','','','','') insert into dtree values('22','4','学员14','index.jsp','blank','','','','') insert into dtree values('23','4','学员15','index.jsp','blank','','','','') select id,pid,[name],url,title,target,icon,iconOpen,[open] from dtree 客户端代码 index.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@page import="com.zsw.biz.TreeNodeBiz;"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>树形菜单</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <link rel="StyleSheet" href="dtree.css" type="text/css" /> <script type="text/javascript" src="dtree.js"></script> </head> <body> <div> <% TreeNodeBiz tnb = new TreeNodeBiz(); %> <script type="text/javascript"> d = <%= tnb.getList("dtree") %> document.write(d); </script> </div> </body> </html> 转换成节点数据转换成js文件 关键代码:
if(list==null || list.size() == 0){
System.out.println("没有节点"); return ""; } StringBuffer contents = new StringBuffer(); contents.append("dtree = new dTree('"+dtree+"');"); for(TreeNode tn : list){ contents.append("/n"); contents.append(dtree+".add('"); contents.append(tn.getId()); contents.append("','"); contents.append(tn.getPid()); contents.append("','"); contents.append(tn.getName()); contents.append("','"); contents.append(tn.getUrl()); contents.append("','"); contents.append(tn.getTitle()); contents.append("','"); contents.append(tn.getTarget()); contents.append("','"); contents.append(tn.getIcon()); contents.append("','"); contents.append(tn.getIconOpen()); contents.append("','"); contents.append(tn.getOpen()); contents.append("');"); contents.append("/n"); } 客户端的代码: 需要导入:dtree.js 和dtree.css
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@page import="com.zsw.biz.TreeNodeBiz;"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>树形菜单</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <link rel="StyleSheet" href="dtree.css" type="text/css" /> <script type="text/javascript" src="dtree.js"></script> </head> <body> <p><a href="javascript: d.openAll();">全部展开</a> | <a href="javascript: d.closeAll();">全部关闭</a> </p> <div> <% TreeNodeBiz tnb = new TreeNodeBiz(); |
Spring多数据源解决方案的更多相关文章
- spring boot(七)mybatis多数据源解决方案
说起多数据源,一般都来解决那些问题呢,主从模式或者业务比较复杂需要连接不同的分库来支持业务.我们项目是后者的模式,网上找了很多,大都是根据jpa来做多数据源解决方案,要不就是老的spring多数据源解 ...
- spring 多数据源一致性事务方案
spring 多数据源配置 spring 多数据源配置一般有两种方案: 1.在spring项目启动的时候直接配置两个不同的数据源,不同的sessionFactory.在dao 层根据不同业务自行选择使 ...
- 基于注解的Spring多数据源配置和使用
前一段时间研究了一下spring多数据源的配置和使用,为了后期从多个数据源拉取数据定时进行数据分析和报表统计做准备.由于之前做过的项目都是单数据源的,没有遇到这种场景,所以也一直没有去了解过如何配置多 ...
- 基于xml的Spring多数据源配置和使用
上一篇讲了<基于注解的Spring多数据源配置和使用>,通过在类或者方法上添加@DataSource注解就可以指定某个数据源.这种方式的优点是控制粒度细,也更灵活. 但是当有些时候项目分模 ...
- Spring配置数据源
Spring在第三方依赖包中包含了两个数据源的实现类包,其一是Apache的DBCP,其二是 C3P0.可以在Spring配置文件中利用这两者中任何一个配置数据源. DBCP数据源 DBCP类包位于 ...
- Spring 管理数据源
Spring 管理数据源 不管通过何种持久化技术,都必须通过数据连接访问数据库,在Spring中,数据连接是通过数据源获得的.在以往的应用中,数据源一般是Web应用服务器提供的.在Spring中,你不 ...
- Spring多数据源的配置和使用
1. 配置多个数据源 最近开发一个数据同步的小功能,需要从A主机的Oracle数据库中把数据同步到B主机的Oracle库中.当然能够用dmp脚本或者SQL脚本是最好,但是对于两边异构的表结构来说,直接 ...
- Spring多数据源的动态切换
Spring多数据源的动态切换 目前很多项目中只能配置单个数据源,那么如果有多个数据源肿么办?Spring提供了一个抽象类AbstractRoutingDataSource,为我们很方便的解决了这个问 ...
- spring 动态数据源
1.动态数据源: 在一个项目中,有时候需要用到多个数据库,比如读写分离,数据库的分布式存储等等,这时我们要在项目中配置多个数据库. 2.原理: (1).spring 单数据源获取数据连接过程: ...
随机推荐
- React Native网络请求
很多移动应用都需要从远程地址中获取数据或资源.你可能需要给某个REST API发起POST请求以提交用户数据,又或者可能仅仅需要从某个服务器上获取一些静态内容--以下就是你会用到的东西.新手可以对照这 ...
- 深入理解MyBatis框架的的配置信息
面对一个框架,最重要的不是说回用其代码就可以了,我们需要了解其思想,这样才能更快更好的掌握这个框架.而对于一个框架,最重要的就是其配置文件的作用及功能了.下面,我就来谈一谈我今天遇到的这个MyBati ...
- 安卓中的消息循环机制Handler及Looper详解
我们知道安卓中的UI线程不是线程安全的,我们不能在UI线程中进行耗时操作,通常我们的做法是开启一个子线程在子线程中处理耗时操作,但是安卓规定不允许在子线程中进行UI的更新操作,通常我们会通过Handl ...
- 探索Antlr(Antlr 3.0更新版)
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明 http://www.blogbus.com/dreamhead-logs/10756716.html <探索Antlr> ...
- ROS_Kinetic_21 使用Qt Creator Plug in即ros_qtc_plugin
更为详细版本请参考: http://blog.csdn.net/zhangrelay/article/details/52214411 结合看更为具体. 首先,先上原版参考: 1 http://wik ...
- StarUML中InteractionOperation的画法
StarUML画InteractionOperation的方法:http://stackoverflow.com/questions/16152278/using-alt-in-sequence-di ...
- 【Unity Shaders】Lighting Models —— 衣服着色器
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- ROS_Kinetic_16 ubuntu中安装使用Matlab和ROS
ROS_Kinetic_16 ubuntu(16.04)中安装使用Matlab(2015b)和ROS(kinetic) 参考网址:http://cn.mathworks.com/hardware-su ...
- Dynamics CRM2013 编辑视图时弹出尚未保存所做的更改警示框
CRM2013中当对视图进行自定义编辑时,总会弹出如下图所示的警示框,一般我们都会选择离开此页来保存我们所做的更改,显而易见的是这又是CRM2013的一个bug 在UR2 for Dynamics ...
- Java 对象在堆中的内存结构
翻译人员: 铁锚 翻译日期: 2013年11月8日 原文链接: What do Java objects look like in memory during run-time? 我们知道,函数每次 ...