论坛首页 Java企业应用论坛

一个支持数据库分布式访问的小框架(更新5)

浏览 22890 次
精华帖 (0) :: 良好帖 (9) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2012-05-02   最后修改:2012-06-04

 

最近写了一个支持分布式数据库访问的小框架,只要是使用PreparedStatement进行sql处理的框架都可以结合使用。例如


hibernate ,ibatis,mybatis。

 

支持分表分库,单数据库事务支持,多数据库事务分布提交(只是自动多次con.commit(),并不具有真正的分布式事务功能)。

 

代码在   https://github.com/akwei/halo-dal


目前本人还不会使用maven进行包管理,所以需要的jar包都放到了代码中。

 

以后会加入读写分离的数据访问方式


欢迎大家多提意见

 

我的新浪微博是 @akweiwei,gtalk:ak478288@gmail.com qq:54501421

 

欢迎交流

 

更新:

对代码进行了优化

已经增加支持读写分离的解析

修改了例子

可以通过代码指定数据源和表,适用于一些无法通过条件进行解析的场景(感谢"程序新手",发现我原先没有对此场景支持)

 

更新2:

新版本已经发布,目前支持sql解析器结果缓存,这样就不用每次都进行解析了。只需要进行替换表名称。目前还没有实现使用antlr进行解析。

 

更新3:

修改了多处bug,谢谢大家在使用中提出的意见,以及找出的bug,目前本人时间有限,测试用例写的不完美。感谢大家帮助我测试。

 

更新4:

在使用sequenece作为id时,请求sequenece的sql语句是没有任何库表信息的。因此会抛出dsKey 为null 的异常。因此在使用时,请尽量先通合适的方式获得最新id。

不在分表分库的操作中首先使用sequence操作。

 

更新5:

修改DALConnection isClosed 方法,当未指定数据源时报错。增加了没有数据源时请求的判断。

目前发现在使用hibernate时会遇到此问题。在mysql中当不使用自增id时,hibernate会获取connection进行一些判断。

 

 

小节一下:


有朋友提出了一些会出现的场景:例如需要对每个节点都要操作,那么无法通过查询条件或者赋值条件来指定解析。这种情况只能说是与业务结合,进行具体的处理操作了。

目前文档还不够完善,没把如何直接指定数据源的操作写出来。如果直接指定数据源,就能实现对每个节点的操作。


感谢 "程序新手"提出的场景。


也希望大家多多挑刺,提出不同的场景,看看能否实现


   发表时间:2012-05-02  
对这两点感兴趣:
1、如何支持分库分表的
2、如何支持xa的
0 请登录后投票
   发表时间:2012-05-02  
kimmking 写道
对这两点感兴趣:
1、如何支持分库分表的
2、如何支持xa的


目前做不做分布式事务,我写的说明可能有问题,抱歉

支持分库分表,原理是自己包装了Connection PreparedStatement DataSource,进行数据库连接延迟加载方式

例如

当使用Spring 配置service事务,service.method运行时,spring事务组件会开启数据库事务,这个时候开启的并不是真正的数据库Connection,而是我包装的一个不具有任何数据库特征的Connection,我类名为DALConnection,当进行PreparedStatement操作时,也是如此,操作的都是DALPreparedStatement,真正进行execute()方法时,这个时候程序进行sql解析,获得条件表达式与值,然后与数据路由规则进行匹配,找到真正的数据源,并开启Connection,创建与数据库连接的PreparedStatement,并把刚才一切对DALConnection , DALPreparedStatement进行的操作真正的执行一遍。

使用时与普通的jdbc hibernate等没有区别,只是多了需要编写路由规则程序的步骤而已。
0 请登录后投票
   发表时间:2012-05-02  
如何路由呢?
就是说对建表有什么要求,对sql有什么要求,如何路由
0 请登录后投票
   发表时间:2012-05-02  
kimmking 写道
如何路由呢?
就是说对建表有什么要求,对sql有什么要求,如何路由

 

和普通建表方式没有区别。

 

简单举例:

 

sql:  select * from user where level=1 order by xxxx;

 

假如需要根据level的值进行分表,那么level条件就需要在表达式中,并且有值.

 

sql解析器就会解析sql,并获得所有表达式的值。

 

然后把分析结果传递给相应的路有规则解析器,解析器就会分析表达式中的值,来判断到哪里获取数据。

 

解析器举例:

 

package parser;

import halo.dal.partition.DALPartitionParser;
import halo.dal.partition.DALPartitionTableInfo;
import halo.dal.partition.analysis.SQLExpression;
import halo.dal.partition.analysis.SQLExpressionSymbol;
import halo.dal.partition.analysis.SQLInfo;

/**
 * 对user表进行分区,根据奇偶方式,将偶数sex放入daltest0.user0, 奇数sex放入daltest1.user1
 * 
 * @author akwei
 */
public class UserParser implements DALPartitionParser {

    public DALPartitionTableInfo parse(String tableLogicName, SQLInfo sqlInfo) {
        DALPartitionTableInfo info = new DALPartitionTableInfo();
        // 从sqlInfo获得条件表达式,由于定义的分区条件为sex字段,那么就需要获取sex字段的表达式
        // /由于获取的表达式会存在多个,例如进行范围判断的情况下,就会出现2个表达式,因此会返回一个数组
        SQLExpression[] sqlExpressions = sqlInfo.getSQLExpressions("sex");
        for (SQLExpression e : sqlExpressions) {
            // sex表达式我们只需要获得sex=?的等号表达式
            if (e.getSqlExpressionSymbol() == SQLExpressionSymbol.EQUAL) {
                Integer l = (Integer) e.getValue();
                // 获得表达式的值之后,进行奇偶判断,判断的结果就是我们获得的真实数据源key与表名称
                // 数据源key就是在创建DALDataSource的时候,写入map的key,这个key与真实的DataSource一一对应
                if (l.intValue() % 2 == 0) {
                    info.setRealTableName("user0");// 真实数据表名称
                    info.setDsName("ds0");// 真实数源key
                }
                else {
                    info.setRealTableName("user1");// 真实数据表名称
                    info.setDsName("ds1");// 真实数源key
                }
            }
        }
        return info;
    }
}
 
0 请登录后投票
   发表时间:2012-05-02  
kimmking 写道
如何路由呢?
就是说对建表有什么要求,对sql有什么要求,如何路由



解析器的编写,并不会入侵到业务代码中
0 请登录后投票
   发表时间:2012-05-02  
思路和我的freyja相识
http://freyja.iteye.com/blog/1412191、
不过经过封装,只需要在需要分库的用annotation标记就行了,执行sql的时候会解析表达式,然后根据annotation注解确定其所在的库、表。
0 请登录后投票
   发表时间:2012-05-02  
ps。分库分表功能是当前一个项目用到的还未完善,一些嵌套sql等支持不好。但是支持的sql包括jdbc Statement

因为解析sql用的是jsqlparser 所以支持大部分sql语句
0 请登录后投票
   发表时间:2012-05-02  
我的读写分离 基于spring+mybatis,大致一样也是基于lazyconnectionProxy。
http://xiaoz5919.iteye.com/blog/1497223
0 请登录后投票
   发表时间:2012-05-02  
看来对这个东西,大家都挺感兴趣,而且动手实践过。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics