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来决定数据存放在哪个数据库中。
配置文件示例:
<beanid="dataSource"class="com.bitfone.smartdm.datasource.DynamicDataSource"><propertyname="targetDataSources">
<mapkey-type="java.lang.Integer">
<entrykey="0"value-ref="dataSource0"/>
<entrykey="1"value-ref="dataSource1"/>
<entrykey="2"value-ref="dataSource2"/>
</map>
</property>
<propertyname="defaultTargetDataSource"ref="dataSource0"/>
</bean>
<beanid="sqlMapClient"class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<propertyname="configLocation"value="classpath:com/bitfone/smartdm/dao/sqlmap/sql-map-config.xml"/>
<propertyname="dataSource"ref="dataSource"/>
</bean>
<beanid="UserInfoDAO"class="com.bitfone.smartdm.dao.impl.UserInfoDAO">
<propertyname="sqlMapClient"ref="sqlMapClient"/>
</bean>
下面是个人在项目中用过的配置方法(以后公布):
程序中的控制代码
public class DbContextHolder{
private static final ThreadLocal contextHolder = new ThreadLocal();
publicstaticvoidsetDbType(StringdbType)
{
contextHolder.set(dbType);
}
publicstaticStringgetDbType()
{
Stringstr=(String)contextHolder.get();
if(null==str||"".equals(str))
str="1";
returnstr;
}
publicstaticvoidclearDbType()
{
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*fromaa;
+------+------+
|id|name|
+------+------+
|1|10|
|1|20|
|1|20|
|2|20|
|3|200|
|3|500|
+------+------+
6 rows in set (0.00 sec)以id分组,把name字段的值打印在一行,逗号分隔(默认)
mysql>selectid,group_concat(name)fromaagroupbyid;
+------+--------------------+
|id|group_concat(name)|
+------+--------------------+
|1|10,20,20|
|2|20|
|3|200,500|
+------+--------------------+
3 rows in set (0.00 sec)以id分组,把name字段的值打印在一行,分号分隔
mysql>selectid,group_concat(nameseparator';')fromaagroupbyid;
+------+----------------------------------+
|id|group_concat(nameseparator';')|
+------+----------------------------------+
|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(distinctname)|
+------+-----------------------------+
|1|10,20|
|2|20|
|3|200,500|
+------+-----------------------------+
3 rows in set (0.00 sec)以id分组,把name字段的值打印在一行,逗号分隔,以name排倒序
mysql>selectid,group_concat(nameorderbynamedesc)fromaagroupbyid;
+------+---------------------------------------+
|id|group_concat(nameorderbynamedesc)|
+------+---------------------------------------+
|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 ifexists(select*fromsysdatabaseswherename='tree') dropdatabasetree go createdatabasetree on ( Name='tree_data',--主数据文件的逻辑名称 FileName='D:/tree_data.mdf',--数据文件的物理名称 Size=5Mb,--主数据文件的初始大小 FileGrowth=20%--主数据文件增长率 ) logon ( Name='tree_log', FileName='d:/tree_log.ldf', Size=3Mb, FileGrowth=10% ) go ifexists(select*fromsysobjectswherename='dtree') droptabledtree go usetree go /*---创建节点表---*/ createtabledtree ( idvarchar(20),--节点编号 pidvarchar(20),--父节点 [name]varchar(20),--节点名称 urlvarchar(20),--连接地址 titlevarchar(20),--节点描述 targetvarchar(20),--Target iconvarchar(20),--图标 iconOpenvarchar(20),--展开状态下的图标路径 [open]varchar(20)--是否展开 ) /*---初始化测试数据---*/ insertintodtreevalues('0','-1','T16班','index.jsp','blank','','','','') insertintodtreevalues('1','0','教师','index.jsp','blank','','','','') insertintodtreevalues('2','0','班干部','index.jsp','blank','','','','') insertintodtreevalues('3','0','组长','index.jsp','blank','','','','') insertintodtreevalues('4','0','学员','index.jsp','blank','','','','') insertintodtreevalues('5','1','班主任','index.jsp','blank','','','','') insertintodtreevalues('6','1','教员','index.jsp','blank','','','','') insertintodtreevalues('7','2','班长','index.jsp','blank','','','','') insertintodtreevalues('8','2','学委','index.jsp','blank','','','','') insertintodtreevalues('9','4','学员1','index.jsp','blank','','','','') insertintodtreevalues('10','4','学员2','index.jsp','blank','','','','') insertintodtreevalues('11','4','学员3','index.jsp','blank','','','','') insertintodtreevalues('12','4','学员4','index.jsp','blank','','','','') insertintodtreevalues('13','4','学员5','index.jsp','blank','','','','') insertintodtreevalues('14','4','学员6','index.jsp','blank','','','','') insertintodtreevalues('15','4','学员7','index.jsp','blank','','','','') insertintodtreevalues('16','4','学员8','index.jsp','blank','','','','') insertintodtreevalues('17','4','学员9','index.jsp','blank','','','','') insertintodtreevalues('18','4','学员10','index.jsp','blank','','','','') insertintodtreevalues('19','4','学员11','index.jsp','blank','','','','') insertintodtreevalues('20','4','学员12','index.jsp','blank','','','','') insertintodtreevalues('21','4','学员13','index.jsp','blank','','','','') insertintodtreevalues('22','4','学员14','index.jsp','blank','','','','') insertintodtreevalues('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"%> <%@pageimport="com.zsw.biz.TreeNodeBiz;"%> <!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN"> <html> <head> <title>树形菜单</title> <metahttp-equiv="pragma"content="no-cache"> <metahttp-equiv="cache-control"content="no-cache"> <metahttp-equiv="expires"content="0"> <metahttp-equiv="keywords"content="keyword1,keyword2,keyword3"> <metahttp-equiv="description"content="Thisismypage"> <linkrel="StyleSheet"href="dtree.css"type="text/css"/> <scripttype="text/javascript"src="dtree.js"></script> </head> <body> <div> <% TreeNodeBiztnb=newTreeNodeBiz(); %> <scripttype="text/javascript"> d=<%=tnb.getList("dtree")%> document.write(d); </script> </div> </body> </html>转换成节点数据转换成js文件 关键代码: if(list==null || list.size() == 0){ System.out.println("没有节点"); return""; } StringBuffercontents=newStringBuffer(); contents.append("dtree=newdTree('"+dtree+"');"); for(TreeNodetn: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"%> <%@pageimport="com.zsw.biz.TreeNodeBiz;"%> <!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN"> <html> <head> <title>树形菜单</title> <metahttp-equiv="pragma"content="no-cache"> <metahttp-equiv="cache-control"content="no-cache"> <metahttp-equiv="expires"content="0"> <metahttp-equiv="keywords"content="keyword1,keyword2,keyword3"> <metahttp-equiv="description"content="Thisismypage"> <linkrel="StyleSheet"href="dtree.css"type="text/css"/> <scripttype="text/javascript"src="dtree.js"></script> </head> <body> <p><ahref="javascript:d.openAll();">全部展开</a>| <ahref="javascript:d.closeAll();">全部关闭</a> </p> <div> <% TreeNodeBiztnb=newTreeNodeBiz(); %> <scripttype="text/javascript"> d=<%=tnb.getList("dtree")%> document.write(d); </script> </div> </body> </html>系统功能与操作权限分配原理(ERP) @author Bob 2012/08/09 我们以前一般做的系统功能操作权限,采用的是在系统功能中定义一个权限字段,并把操作权限的id以;分割符号保存在该字段中 ;一下介绍一种简便的权限分配原理; 由于本人文字功底有限.直接以图说明原理. 1.系统功能表中有一个prev字段保存操作权限 ,类型为int 2,操作权限表中的数据为 0 查看 1 增加 2 修改 3 删除 权限分配原理:prev=2^1+2^2+2^n.....; 至于如何在功能表中检测有哪些权限(以后在公布) 如果 prev=5 哪么 prev=2^0+2^2 既本功能有查看,修改功能 |