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 单数据源获取数据连接过程: ...
随机推荐
- 使用Swift开发一个MacOS的菜单状态栏App
猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/52054107 ...
- 学习笔记6-Android查看应用输出的错误信息 如何部署应用到真实手机 发布软件
查看应用输出的错误信息 1. 通过LogCat窗口查看信息 右上角图标可以筛选不同级别的信息(比如info等). 右上角的+可以进行信息筛选 把应用部署到真实手机 1. 要把手机的 ...
- UNIX环境高级编程——线程属性之分离属性
说到线程的分离状态,我认为,之所以会有这个状态,是因为系统对某些线程的终止状态根本不感兴趣导致的. 我们知道,进程中的线程可以调用: int pthread_join(pthread_t tid, v ...
- Mysql join语句的优化
Mysql4.1开始支持SQL的子查询.这个技术可以使用SELECT语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查询中.使用子查询可以一次性的完成很多逻辑上需要多个步骤才能完成的 ...
- 【一天一道LeetCode】#125. Valid Palindrome
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...
- android的PackageManagerService详解
PackageManagerService主要是一个包的管理服务,在开机的时候会解析以前保存的一些安装包的相关数据,android运行过程中新安装的apk也会保存到PackageManagerServ ...
- android:layout_gravity和gravity的区别
文章转自http://blog.csdn.net/shakespeare001/article/details/784346,给出了很详细的解释. 1.首先来看看Android:layout_grav ...
- (NO.00003)iOS游戏简单的机器人投射游戏成形记(九)
现在按住手臂可以非常自然和舒服的旋转了,丝般顺滑:移动停止,旋转立即停止,没有什么惯性影响了. 以上一共介绍了2中旋转方式,到底采用哪种方式呢?其实看实际游戏的需求和个人的喜好了.本猫在Level中添 ...
- 小强的HTML5移动开发之路(11)——链接,图片,表格,框架
来自:http://blog.csdn.net/dawanganban/article/details/18098193 一.HTML是什么? HTML(hypertext mark-uplangua ...
- java的制作"时间账本"
一直以来我都感觉自己的时间过得好荒废啊,貌似只是打开了一个网页链接的时间,一个下午便过去了:仿佛就是看了看空间,刷了刷微信,一天就过去了.哈,当然这是夸张的说法.但是我仔细地算了一下,大概我们每个人每 ...
动态生成树型菜单