DAS DAS简介DAS是信义科技开发的数据库访问中间件。它是一个集成的关系数据库访问解决方案,包括数据库管理、ORM、动态SQL构造和数据库与表分离。
看到这里,你会说少年!有那么多ORM框架和子数据库、子表组件可以选择,比如Hibernate、Mybatis、mycat、分片jdbc,还有我们最爱的携程DAL。为什么要反复造轮子?
答案很简单,这些工具不好用!DAS是我们最新的高科技车轮。
警告!前方高能!非资深开发人员应尽快撤离。请握紧鼠标,握紧键盘!
你一定对DAS的产品定位感到惊讶。既然想做数据库中间件,为什么不像其他产品一样从JDBC或者数据库协议层入手,在传统数据库上划分数据库和表或者重新开发数据库引擎?多牛逼啊!现有程序无需修改即可无缝移植。DAS为什么提供ORM功能?
在回答这个问题之前,我们先简单回顾一下流行的数据库编程过程。这有助于理解DAS的产品定位。
mybatis和Hibernate发明的时候,还没有纵横数据库扩展、子数据库、子表等概念,设计时自然不会考虑。现在,任何互联网公司每天都会产生大量的数据。所以,一个严肃的数据库项目往往会同时使用ORM工具和子数据库、子表组件。无论是ORM还是子数据库、子表组件,一般都需要繁琐的配置。唯一的区别是难度是可以忍受的还是不鼓励的。
以最流行的mybatis任意数据库和表组件为例。如果你是一个高级CRUD boy,你一定非常熟悉下面的套路。在开始在图的中间写下最终的实际DAO代码之前,您需要解决另外四个问题:
当你匆忙做这些配置,第一次测试的时候,十有八九不会成功。此时不要气馁,因为更糟的还在后面。当你在项目中使用独立的ORM和子数据库、子表组件时,你会难过到流泪:
你见过用XML写代码的人吗?这就是mybatis以XML形式存储表结构和动态SQL语句的方式,它与Java代码分开,用于实际调试。请告诉我如何用XML调试?虽然mybatis的这个设计已经过时了,但是它基于注释的新设计更糟糕。你见过上面有十层奶油,下面只有一层蛋糕的奶油蛋糕吗?Mybatis的注解似乎就是这种感觉。我想添加一个新方法。我必须首先更改XML,然后生成DAO接口,然后才能使用它。礼虽满,编程效率极低。或者你可以试着用注释写SQL,这也挺酷的。子数据库和子表的配置通常比较复杂,基本没有自动化工具的支持,全靠手工。这种体验就像蒙着眼睛在装满图钉的罐子里抓泥鳅一样刺激。到现在我还清楚地记得那次不得不硬着头皮把某个子数据库、子表组件的用户手册看了三遍的挫败感。最好的东西总是在最后。你会发现不同环境的Datasource配置往往放在同一个项目中,通过profile或者其他方式来区分。打包阶段很容易出错,这种错误只有在部署阶段才能发现。故障排除前下载解压极其麻烦。更不用说生产数据库密码泄露的安全隐患了。随着数据库和表格的增长,做这些事情的痛苦指数从痛苦迅速发展到无限痛苦。如果你觉得这没什么,那么你一定是那个可以享福的人。当最终克服所有困难的代码能够工作的时候,你会发现最终的DAO代码相对于整体的配置和代码量来说只占了很小的一部分。而在这部分代码中,只有极小一部分是真正有用的。如果你不相信我,看:
publicstaticvoidmain(string args)throwsio exception { Inputstrean resource asstream ResourcesogetResourceasstrean(" cc/SQL 1 up config . XML ");sq1 session factory SSF enew sq1 sessionactoryBullder()。build(resourceAsstream);///mapper是UserMapper接口的实现类。
UserMapper mapper=sqlSession。getMapper(用户映射程序。class);
user u=mapper . finduserbyid(10);
system . out . print 1n();
}
以上是典型的mybatis代码。除了倒数第二行代码,其他的都是什么?随便抢个两毛钱的红包,何必“敲那么多人的头”?剔除注释和无关代码,真正有用的代码只占1/5。你不觉得这个比例很可笑吗?为了交付这一点点代码,付出的代价是如此之高。
“大”,你觉得不对劲吗?
src="https://tupian.lamuhao.com/pic/img.php?k=数据库都有哪些中间件,数据库都有哪几种类型2.jpg">其实要查询,真正关键的信息就是数据库名和查询语句而已。评价一个设计的的好坏只要看实现一个需求在多大程度上只需要提供必要信息。额外步骤越多,设计越失败!作为参考,请思考餐厅用餐和自己买菜做饭的区别。
作为一个老程序员,我已经厌倦了使用破烂工具。人嘛,要对自己好一点,诚实一点。一个人性化的数据库访问框架应该是这个样子:
具备简洁明了的 API,99% 的操作都能一步搞定,使用起来如丝般顺滑。使用面向应用,面向数据对象这种高级抽象,而不是链接,事务这类极易用错的底层概念。提供基于 Java 的动态 SQL 生成器。在同一个上下文里写 SQL 和写代码,不用切来切去链接,事务之类的统统由框架搞定,不用操心资源的打开,关闭,泄露啥的,没有使用就没有伤害。API 既简单又复杂。既能适应一般情况,又能处理特殊情况。别问,就要。内置分库分表能力,不用再单独集成第三方组件。分库分表配置必须极简单,连我都能学会,当然最好别学。如果你问一个研发人员这世界上什么最痛苦?他一定会回答你学习新技术最痛苦。如果要再上一个档次,那就是要学那种要花很多功夫学习却会隔很长时间才用一两次的技术,对,说的就是分库分表配置这种。不要让我手工编辑任何 XML 或配置文件,都已经 2020 年了,在几万块的 MAC 上写 XML,就像参加豪华晚宴却蹲在椅子上吃饭一样,像什么样子。如果实在免不了要配置,那必须提供能配得上我一指禅的最好的编辑器。只用写 DAO 相关代码,其他一概不管。于是 2018 年在时任 CTO 的规划下,我们信也科技基础组件团队决定自己动手搞一套符合自己心意的数据库访问中间件,这就是
信也 DASDAS 是 Database Access Service 的缩写。DAS 的目标就是给研发人员提供一个一站式的数据库访问框架,让研发人员用最简单直接的方式开发数据库访问代码,实现上面所有“非分”的想法。
为实现这个目标,DAS 提供:
同时具备 ORM 和分库分表能力的客户端 DAS Client ;基于 WEB 页面的数据库配置管理和代码生成工具 DAS Console ;可选的基于代理模式的 DAS Server。应用在直连和代理之间切换无需改代码,也不用知道;
但 DAS 的真正的核心优势不是这些组件,我们 build 了一个专业的团队,7*24 小时主动为程序员服务,帮大家搞定从原子到宇宙尺度的任何数据库问题。
在信也科技,研发人员发邮件告诉 DAS 团队各个环境的数据库配置和逻辑数据库信息,DAS 团队通过 DAS Console 配置好并自动同步到公司的配置中心后,用户只要在自己的项目里面引入 DAS Client 的依赖就可以开始直接写代码。对,你没有看错,直接开始写代码,无需任何的本地配置工作。我们把中间件产品的研发从交付组件提升到交付服务的层面。
这,才是我们成功的秘密!<撒花>
DAS 核心设计初探你心中一定冷笑,吹吧你!那让我们从技术角度看看 DAS 的核心 DAS Client 到底长什么样。
DAS Client 的设计遵从分层抽象原则,从上到下分为:
1. DAO 层,一个完整的 ORM 框架。关于编程所有美好的想象都在这里。
2. 分库分表层。抽象数据库操作差异,以统一的方式处理数据的路由与合并。
3. 执行层。操作底层数据库完成实际工作,封装数据源,链接与事务。
DAO 层是程序员使用最频繁的部分,今天会重点介绍这一部分,其他部分会在未来会逐一提供,请关注我们的“拍码场”公众号。
DAS ORM 简介:
DAS ORM 的主要由预定义 DAO 类 DasClient,SQL 创建工具类 SqlBuilder 和特殊操作指令类 Hints 组成。下面一一介绍。
DasClientDAS ORM 的核心是 DasClient 类,来看看里面提供了啥方法:
DasClient 提供了几乎所有常见的 ORM 操作,开箱即用,不需要用户生成任何 DAO 接口或实现。
别跟我“扯犊子”,上代码!
OK!猜猜看用 DAS 实现一个查询操作需要几行代码?
Person pk = new Person();
pk.setName(“test”);
DasClient dao = DasClientFactory.getClient(“logicDbName”);
List plist = dao.queryBySample(pk);
客户端创建到使用,两行代码完事,是不是很简单粗暴?像我说的一样,如果你要完成一个查询,你需要提供就只是数据库名和 SQL,这里 SQL 用 sample data 表示。除此以外,没有多余动作。没有 session,没有事务,也没有 connection。只要写的代码足够少,BUG 就不会追上我。这就是传说中的极简编程风
通过这种预定义 API 的方式能节省多少代码呢?再以一个实际例子对比一下完成同样功能 mybatis 和 DAS 之间代码量:
Mybatis mapping:
select distinct ‘false’ as QUERYID, from strategyaccountdetailtableSuffixorderbytableSuffixorderby{orderByClause}
DAS 对应代码:
public List selectByExample(Strategyaccountdetail detail) throws SQLException { return client.queryBySample(detail);
}
看到区别了吗?在不需要写一行 XML 的情况下,DAS 用一行代码就可以搞定 mybatis 需要十几行,甚至几十行配置才能完成的功能。其实上面显示的还只是完成这个功能完整 mybatis 配置的一小部分配置,不过已经足够说明我并没有吹牛
SqlBuilder你一定会想,按样例查询这个例子还是非常容易提供通用实现的,如果要根据各种条件生成复杂,动态的 SQL 怎么办?是不是要写很多 if-else 语句自己拼?图样!这时候就要 SqlBuilder 出马了。还是让我们看看实际的代码对比: Mybatis mapping:
select * from (select ROW_NUMBER() OVER ( ORDER BY inserttime DESC ) rownum, from strategyaccountdetail{tableSuffix} WITH(NOLOCK)where userid = #{userid,jdbcType=INTEGER} and strategyid = #{strategyid,jdbcType=VARCHAR} and typeid = #{typeid,jdbcType=INTEGER} and inserttime
DAS 对应代码:
public List selectListByUserIdExample(Long userId, String strategyid, Integer typeId,
Date beginInserttime, Date endInserttime, Integer pageNum, Integer pageSize) throws SQLException {
SqlBuilder builder = SqlBuilder.selectAllFrom(definition).where().allOf(definition.Userid.eq(userId),definition.Isactive.eq(1),
definition.Strategyid.eq(strategyid).nullable(),
definition.Typeid.eq(typeId).nullable(),definition.Inserttime.greaterThanOrEqual(beginInserttime).nullable(),
definition.Inserttime.lessThanOrEqual(endInserttime).nullable()).
orderBy(definition.Inserttime.desc()).into(Strategyaccountdetail.class).offset(pageNum, pageSize).withLock(); return client.query(builder);
}
使用 SqlBuilder 的 DAS 的 code 是不是还是一样紧致光滑?有人会说最新的 mybatis 也有 SqlBuiler 嘛。那我们就也比一比,不要说我骗人: Mybatis Sql builder:
public string selectPersonLike(final String id, final String firstName, final string lastlame) 《
return new SQL() {
{
SELECT(“P. ID, P.USERNAIE, P.PASSHORD, P.FIRST _NANE, P.LAST NAME”);
FROM(“PERSON P”) if (id != null) {
WHERE(“ P.ID like#{id}”);
} if (firstlame != null) {
WHERE(“P.FIRST MAE like #{firstliase}”);
} if (lastlame != null) {
WHERE(“P.LAST NAMIE like #{lastName}”);
} ORDER BY(“P.LAST. NAME”);
}
}.toString();
}
DAS SqlBuilder:
public SqlBuilder seletPersonLike(final string id, final String firstlane, final string lastName) {
Person.PersonDefinition P = Person.PERSON; return sqlBuilder.selectAllFrom§ where().
allOf(
p.d.like(id).nullable(),
p.firstName.like(firstNane).nullable(),
p. lastNare .1ike(iastName).nullab1e()
).orderBy(p.lastName);
}
明显还是 DAS 的 SqlBuilder 设计更出色!
Hints一步到位的提供 API 会存在一个设计风险,那就是任何操作都会存在特殊情况。比如一个简单的插入操作,就存在很多变体:
1. 在存在自增 ID 的情况下生成自增 ID
2. 在存在自增 ID 的情况下使用自定义 ID
3. 在存在自增 ID 的情况下生成自增 ID 并将生成的 ID 设置到输入实体
4. 等等
普通的做法是为每种特殊做法提供 overload 的方法,有几种特殊情况就提供几个方法。按照这种思路发展下去,方法的数量很快就会多到失控。如何才能确保在一个精简的 API 集合上提供尽可能多的特殊操作呢?这就轮到 Hints 登场了。
你可能注意到 DasClient 的方法除了必要参数外,往往还会带一个 Hints。这个 Hints 要么是以可变参数存在,要么是作为必要参数的一个属性。DAS 利用 Hints 传递特殊指令,帮助用户处理灵活多变的场景。以插入单条记录为例,API 长这样:
public int insert(T entity, Hints…hints) throws SQLException
调用的时候既可以只传 entity:
dao.insert§;
也可以传最多一个 hints
dao.insert(p, hints.insertWithId());
无论哪种情况,方法只有一个。 虽然 Hints 也算不上脑洞特别大的发明,但与 ORM 结合得如此之紧密自然,别无分号。这种设计带来的便利是巨大的。不信可以参考一下如果用独立的分库分表组件会怎样实现:
// Sharding database and table with using hintManager ,
String sql = “SELECT * FROM t order”; try (HintManager hintManager = HintManager.getInstance(;
Connectlon conn = dataSource.getConnection();
PreparedStatement preparedstatement conn. prepareStatement(sq1)) {
hintManager.addDatabaseShardingValue(“t_order”, 1);
hintManager.addTableShardingValue(“t_order”, 2); try (ResultSet rs = preparedStatement.executeQuery()) { while (rs.next()) { //…
}
}
}
上面需要 3 行独立代码完成的 Hints 相关工作。倒不是说这个分库分表组件设计的不好。除了 TiDB 或 Amazon Aurora 这种真正的分布式数据库之外,绝大多数基于传统数据库之上的分库分表组件都难以做到完全的对应用代码透明。在特殊场景下都需要以某种方式传递特殊指令。如果依赖于现有 ORM 工具或基于 JDBC,就会存在类似上面这种很不自然的代码。
而 DAS 通过将 Hints 与 ORM 接口结合的方式,完美的解决了特殊与一般的矛盾。同样的事情 DAS 只需要一行:
List<Person) plist = dao.query(selectAllFrom§. setHints(Hints.hints().shardValue(1).tableShardValue(2)));
在推广过程中我们还发现一个有趣的事情。就是我们以为用户喜欢透明的分库分表,但事实上,出于各种原因,用户用的最多的反而是直接指定分库分表。当然利用 Hints 可以很简单的做到:
List plist = dao.query(selectAllFrom§.setHints(Hints.hints(). inShard(1).inTableShard(2)));
自研 ORM 还有一个额外的好处。那就是虽然从成本还有技术的方面来看,分库分表技术目前还有市场,但长远来看,这大概率是一种过渡性的技术。即使哪天人们完全解决了分布式数据库的性能和一致性问题,也还是需要某种面向应用的 ORM 技术来实现灵活多变的需求。这样 DAS 就可以继续发挥作用。从今天的标准来看,DAS ORM 的设计在易用性和灵活性上已经达到了能达到的极限。
总结DAS 完美结合了 ORM 和分库分表功能,其产品定位是进可攻,退可守。根据公司内部实际使用效果来看,使用 DAS 能极大提高研发效率,减少代码量和出错概率,再也没有因配置导致的各种故障。
有一次偶尔路过听到一个总监和下面 tech leader 的对话,总监问如果技术输出,新的代码里面能否不用我们的 DAS,leader 微笑着但坚定的回答,不行,DAS 很好用的,我要用。
对我们做框架的程序员来说,还有什么比一句好用更高的评价吗?
是好东西就要拿出来大家一起用,DAS 已经开源,并提供了详尽的文档供大家参考,请大家尽情 star~
GitHub 地址: https://github.com/ppdaicorp/das
关注我并转发此篇文章,私信我“领取资料”,即可免费获得InfoQ价值4999元迷你书!
- 上一篇:抖音红人戴菲,抖音红人排行榜怎么弄
- 下一篇:所有的洋酒图片,所有的洋酒都要兑着喝吗