随着企业规模扩张和业务量的急剧增加,作为系统核心的数据库相关开发也会经历一个由单一团队发展为多团队;由单机扩张到集群;由单数据库发展为多数据库;由采用单一数据库产品到多种数据库产品并存的过程。
伴随这一过程的是如何管理数据库扩展,如何规范数据库访问,如何保护数据库投资,如何应对访问量增加,如何预防安全问题等一系列挑战。
作为国内在线旅游行业的翘楚,携程也曾经面对同样困扰。为了应对这些挑战,实现企业10倍速发展,携程开发了具有自己特色的数据库访问框架Ctrip DAL。
Ctrip DAL支持流行的分库分表操作,支持Java和C#,支持Mysql和MSSqlServer。使用该框架可以在有效地保护企业已有数据库投资的同时,迅速,可靠地为企业提供数据库访问层的横向扩展能力。
整个框架包括代码生成器和客户端。工作模式是使用代码生成器在线生成代码,通过DAL客户端完成数据库操作。生成器具有丰富的向导指引,操作简单清晰,既可以批量生成标准DAO,也可以在方法级别定制数据库访问。客户端则可以简单地通过标准的maven方式添加依赖。
Ctrip DAL与一般数据库框架最大的不同是从企业跨部门的角度,统一管理数据库相关资源。通过部署代码生成器,企业可以做到有效的管理全公司的DAL开发团队,明确数据库归属和定制数据库访问。通过代码生成器生成的标准DAO代码与客户端配合使用,可以大幅提高工作效率,保证代码质量。解决了业内常见的伴随业务成长而带来的系统维护困难,开发效率低下,代码风格五花八门,代码质量参差不齐等痛点问题。
为了适应不同公司的实际情况,DAL定义了丰富的扩展接口,覆盖了从数据源管理,数据库映射,连接串读取到自定义访问方式等等方方面面的功能。同时为了方便系统监控还内置了系统状态,日志和统计模块。
Ctrip DAL由携程技术中心框架部DAL团队开发,历经3年不断打磨,在长期的实际使用中吸收了大量用户反馈。目前携程超过117个独立DAL团队通过代码生成器管理数据库和创建DAO。2000多个应用在使用DAL框架,占携程所有数据库应用总数超过90%。
本次开源的产品包括代码生成器和Java客户端,C#客户端也将近期开源。DAL各个组件的安装和使用都有详细的文档说明,开箱即用。 通过开源携程自身使用DAL框架,携程希望在满足自身需求的同时,服务于广大企业,并继续为中国方兴未艾的开源运动出点力。
Dal的定位是数据库访问层。是以数据访问类(dao)的形式出现。Dal包括生成的dao代码和dal client底层api。Dal底层使用标准的数据库访问协议访问实际的数据库。
dal本身不是数据库,也不实现数据库协议。Dal依赖具体的数据库实现数据访问的工作。
Dal主要功能是ORM,sharding等。Dal支持简单的基于单库的事务,但dal不支持分布式事务
Dal也不支持数据库同步工作。数据库同步请使用数据库自带或第三方工具
Dal的推荐用法是在公司的内网安装一个code gen。code gen里面配置开发环境的数据库。通过code gen生成各种DAO。用户直接使用DAO来完成相应的工作。
Dal不推荐通过自己调用底层API的方式来完成数据库操作,希望大家利用code gen完成工作。这样做的好处是一旦数据库schema发生变更,仅仅需要重新生成代码即可。自己如果手写代码,一旦重新生成有可能会冲掉原来手工的改动。
典型的应用程序分为如下几层
用户的应用逻辑层。通过调用下层的Domain Data Access Layer完成所有跟数据库相关的操作。Domain Logic Layer相关的代码由用户维护。
一般是指通过DAL code generator生成的DAO。目前支持基于单表/视图/存储过程/自由查询/手工SQL的DAO生成。
在无法满足要求的特殊情况下可以手写DAO。例如存在大量的通用操作,没必要为每个表生成单独的DAO。可以生成一个通用的DAO来满足其要求。以避免生成大量雷同的DAO类。降低维护成本和出错风险
该层code由用户的DAL team维护。用户的DAL Team负责使用Code Generator生成DAO,满足特定用户的数据库访问需求。
一般来说如果team的开发人员比较多,建议成立相对独立的DAL Team;如果人数比较少,可以明确责任人,成立虚拟的Dal Team。
为实现通用的数据库访问层而提供的底层API和相关的辅助类。该API为其上的Domain Database Access Layer提供支持。该层包含所有数据库操作最底层的API和针对常用操作提供的的DAO帮助类。
DAO帮助类目前包含支持单表和自由查询的DAO。同时由Code Generator生成的单表/查询相关的DAO会将相关的操作交给这些DAO帮助类去处理。这样做可以避免在Domain Database Access Layer生成大量的重复代码,并且保证质量。
DAL Client由DAL Core Team维护。DAL Core Team负责维护Code generator,DAL Helper DAO,DAL Core API等cross team的工具。
注意,DAL Core Team不同于用户自己的Dal Team。
Object Insert<T>(T obj) where T : class, new()
方法族Object InsertByComplexPk<T>(T obj) where T : class, new()
方法族Boolean BulkInsert<T>(IList<T> list) where T : class, new()
方法族IQuery<T> GetQuery<T>() where T : class, new()
IList<T> GetAll<T>() where T : class, new()
方法族IList<T> SelectListOfSingleField<T>(String sql)
方法族IList<T> SelectList<T>(String sql) where T : class, new()
方法族IList<T> SelectList<T>(IQuery query) where T : class, new()
方法族IList<T> SelectListByAdapter<T>(String sql) where T : class, new()
方法族IList<T> SelectListByAdapter<T>(IQuery query) where T : class, new()
方法族IList<T> ExecListBySp<T>(String procName, StatementParameterCollection parameters) where T : class, new()
方法族T GetByKey<T>(Object key) where T : class, new()
方法族T SelectFirst<T>(String sql) where T : class, new()
方法族T SelectFirst<T>(IQuery query) where T : class, new()
方法族T VisitDataReader<T>(String sql, Func<IDataReader, T> callback)
方法族T VisitDataReaderBySp<T>(String procName, StatementParameterCollection parameters, Func<IDataReader, T> callback)
方法族DataTable SelectDataTable(String sql)
方法族DataTable ExecDataTableBySp(String procName, StatementParameterCollection parameters)
方法族DataSet SelectDataSet(String sql)
方法族DataSet SelectDataSet<T>(IQuery query) where T : class, new()
方法族DataSet ExecDataSetBySp(String procName, StatementParameterCollection parameters)
方法族IDataReader SelectDataReader(String sql)
方法族IDataReader ExecDataReaderBySp(String procName, StatementParameterCollection parameters)
方法族Object ExecScalar(String sql)
方法族Object ExecScalarBySp(String procName, StatementParameterCollection parameters)
方法族Int32 Update<T>(T obj) where T : class, new()
方法族IUpdatePartial<T> GetUpdatePartially<T>() where T : class, new()
Int32 UpdatePartially<T>(IUpdatePartial<T> partially, T obj) where T : class, new()
方法族Int32 ExecNonQuery(String sql)
方法族void ExecSp(String procName, StatementParameterCollection parameters)
方法族Int32 Delete<T>(T obj) where T : class, new()
方法族