本文转载自微信公众号「后端Q」,作者conan。转载本文请联系后端Q公众号。
简介
Ctrip DAL是携程框架部开发的数据库访问框架,支持代码生成和水平扩展。其由携程技术中心框架部DAL团队开发,历经3年不断打磨,并在长期的实际使用中基于大量的用户反馈不断优化。
开源范围包括代码生成器,Java客户端和C#客户端。
背景
随着企业规模扩张和业务量的急剧增加,作为系统核心的数据库相关开发也会经历一个由单一团队发展为多团队;由单机扩张到集群;由单数据库发展为多数据库;由采用单一数据库产品到多种数据库产品并存的过程。伴随这一过程的是如何管理数据库扩展,如何规范数据库访问,如何保护数据库投资,如何应对访问量增加,如何预防安全问题等一系列挑战。作为中国在线旅游行业的翘楚,携程也曾经面对同样困扰。为了应对这些挑战,实现企业10倍速发展,携程开发了具有自己特色的数据库访问框架Ctrip DAL。
Ctrip DAL支持流行的分库分表操作,支持Java和C#,支持Mysql和MS SqlServer。使用该框架可以在有效地保护企业已有数据库投资的同时,迅速,可靠的为企业提供数据库访问层的横向扩展能力。整个框架包括代码生成器和客户端。工作模式是使用代码生成器在线生成代码和配置,通过DAL客户端完成数据库操作。生成器具有丰富的向导指引,操作简单清晰,即可以批量生成标准DAO,也可以在方法级别定制数据库访问。客户端则可以简单的通过标准的maven方式添加依赖。
Ctrip DAL与一般数据库框架最大的不同是从企业跨部门的角度,统一管理数据库相关资源。通过部署代码生成器,企业可以做到有效的管理全公司的DAL开发团队,明确数据库归属和定制数据库访问。通过代码生成器生成的标准DAO代码与客户端配合使用,可以大幅提高工作效率,保证代码质量。解决了业内常见的伴随业务成长而带来的系统维护困难,开发效率低下,代码风格五花八门,代码质量参差不齐等痛点问题。
代码生成器
代码生成器允许用户创建Dal团队,组织开发人员,管理数据库,创建DAO并生成代码和配置。与一般基于JDBC driver的DB sharding产品不同的是,代码生成器生成的代码和配置可以直接拿来实用,完全无需用户写一行代码和配置。做到了只需开发人员关心业务逻辑,而把繁琐的数据库相关的编码和配置任务全部交给DAL。由于Ctrip DAL完全在DAO这层工作,也没有什么这种SQL语句不支持,那种SQL语句不能用的情况。同时传递hints的方式也非常自然,每个方法都自带hints的接口,需要DAL额外做什么可以直接按给定的已有名字来设置,无需改写原始的sql来添加怪异的注释。
客户端简介
客户端配合代码生成器生成的代码来完成用户的数据库访问操作。通过Dev和QA两方面双重自动化测试来保障质量,覆盖率达到99%,并经过生产实际实用的的长期严格检验。为了适应不同公司的实际情况,DAL客户端定义了丰富的扩展接口,覆盖了从数据源管理,数据库映射,连接串读取到自定义访问方式等等方方面面的功能。同时为了方便系统监控还内置了系统状态,日志和统计模块。
C#客户端 API列表
以下这些API位于BaseDao类中 方法族说明:除了所示的方法之外,至少还包含一个带有IDictionary hints参数的重载方法。
注意:增删改均适用的API被归类至Update系列
- Create
- 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() 方法族
- Retrieve
- 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) 方法族
- Update
- 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) 方法族
- Delete
- Int32 Delete<T>(T obj) where T : class, new() 方法族
https://github.com/ctripcorp/dal