我们为Hibernate构建了一个CockroachDB方言

2020-09-22 02:57:46

产品本文最初发表于2017年,当时宣布CockroachDB对Hibernate的支持处于测试阶段。今天,我们很兴奋地宣布一些重大消息:Hibernate的CockroachDB方言正式可用!🥳。

Hibernate现在为CockroachDB提供了一流的支持。在这篇博客文章中,你可以阅读更多关于这种方言的信息,以及我们到达那里的旅程。

我们正在努力使CockroachDB具有可伸缩性和健壮性,但使用起来很简单。我们解决这一问题的一种方法是添加对现有对象关系映射器(ORM)的支持,这使得开发与CockroachDB交互的应用程序变得又快又容易。为了确定首先支持哪些ORM,我们询问了我们社区的客户和用户,进行了开发人员调查,并进行了其他研究。Hibernate出现得最频繁,可能是因为Java的大型开发人员社区和Hibernate在那个世界中的受欢迎程度。这篇文章主要是关于Hibernate兼容性的,但我们最初所做的一系列SQL兼容性工作也为其他ORM兼容性铺平了道路。

当我们第一次开始这个项目时,我们有一个雄心勃勃的目标,那就是获得对五个ORM的支持。Hibernate在我们的列表中排在首位,有两条潜在的前进道路:

实现Hibernate运行所需的SQL功能。这是可行的,因为Cockroach支持Postgres有线协议及其大部分语法。因为许多ORM支持PostgreSQL,所以这个选项涉及添加ORMS需要但CockroachDB缺乏的SQL特性。

为每个ORM创建一个CockroachDB适配器。尽管SQL有一套标准,但每个常用数据库都与标准和/或专有SQL功能有很大的不同。这要求ORMS为它连接的每个数据库都有一个适配器。因此,选项2是创建一个使用CockroachDB已经支持的特性执行ORM特定任务的扩展。

在2017年,我们希望快速发布对Hibernate的支持。此外,在一些调查之后,我们发现其他ORM需要的SQL特性有很大重叠。所以,我们一开始选择了1号方案。当时,我们决定通过适应他们期望的接口来利用预构建的适配器,从长远来看,与为每个单独的ORM或工具创建自定义适配器相比,使用预构建的适配器会更省力。

那么,这些功能是什么呢?ORMS发出两种基本类型的查询。第一组由CRUD(创建、读取、更新、删除)查询组成。考虑到我们现有的SQL语句实现,这相对简单。存在一些小问题,例如日期和时间格式不兼容,但修复起来很简单。

ORM的重要职责之一是确保数据库中的表、列和索引与代码定义的模型一致。例如,考虑以下Hibernate ORM模型:

私有静态最终SessionFactory sessionFactory=new configuration().configure(";hibernate.cfg.xml";).addAnnotatedClass(Account.class).buildSessionFactory();@Entity@Table(name=";accounts";)public静态类帐户{@ID@Column(Name=";id";)public long id;@Column(Name=";Balance";)Public Long Balance;}。

如果ACCOUNTS表不存在,则创建ACCOUNTS表。Hibernate“知道”表,因为函数调用addAnnotatedClass(Account.class)。

如果id列不存在,则将其添加到Accounts,并使其成为Accounts的主键。

Hibernate知道它希望Accounts*表如何基于@Table、@Column和@ID注释进行结构化。现在,它需要知道帐户是否已经存在,如果存在,它的当前架构是什么。

模式同步使数据库模式与模型一致(例如,上例中的Account)。为此,Hibernate必须通过数据库提供的机制检索数据库模式。

INFORMATION_SCHEMA是SQL定义的一组标准视图,用于公开数据库结构以供客户端自省。不幸的是,我们测试的ORM在连接到PostgreSQL时不使用此功能。相反,它们使用特定于PostgreSQL的PG_CATALOG模式中的关系。因此,我们已经实现了Hibernate所需的PG_CATALOG视图的子集。这允许Hibernate应用程序连接到CockroachDB,就像它是PostgreSQL一样。

此过程相对简单,但涉及对SQL执行、类型系统和各种其他代码的重大更改。它还运行了以前未得到充分利用的部分SQL引擎。例如,考虑在运行示例应用程序时Hibernate发出的以下查询:

选择NULL::TEXT作为PKTABLE_CAT,选择pkn.nspname作为PKTABLE_SCHEM,当';c';时选择[15行省略]case con.confdeltype,当';c';时选择0,当';d';时选择2,当';d';时选择4,当';r';时选择1,当';a';时选择1。则从pg_Catalog.pg_nampace PKN、pg_Catalog.pg_class PKC、pg_Catalog.pg_attribute PKA、pg_Catalog.pg_namepace fkn、pg_Catalog.pg_class fkc、pg_Catalog.pg_attribute fkc、pg_Catalog.pg_straint con、pg_Catalog.Generate_Series(1,32)pos(N)、pg_Catalog.pg_Depend dep中的其他3个NULL结尾为delete_Rule,[省略8行]。Pg_Catalog.pg_class pkicWHERE pkn.oid=pkc.relnampace and pkc.oid=pka.attrelid and pka.attnum=con.confkey[pos.n]and con.confrelid=pkc.oid and fkn.oid=fkc.relnampace and fkc.oid=fka.attrelid and fka.attnum=con.conkey[pos.n]and con.conrelid=fkc.oid and con.contype=';F';and con.oid=dep.objid and pkic.oid=dep.refobjid and pkic.relkin=';i';and Department.classd=';pg_Constraint';::regclass:OID and dep.refategd=';pg_class';::regclass::OID and fkn.nspname=';public';和fkc.relname=';order';order by pkc.nspname,pkc.relname,con.conname,pos.n;order';Order';Order'。

您看了这个查询几分钟后仍然不明白它试图做什么,这是合理的。此查询使用PG_CATALOG中的关系检索公共模式中ORDERS表的外键。

Hibernate在使用PG_CATALOG而不是INFORMATION_SCHEMA方面并不是唯一的。其他几个ORM,包括我们在2017年ORM兼容性测试中优先考虑的其他四个ORM,也使用PG_CATALOG。幸运的是,我们还确认这些ORM大多使用与Hibernate相同的PG_CATALOG部分。

自从最初的Hibernate测试版支持以来,我们已经大大改进了CockroachDB的Postgres兼容性。即便如此,我们还是想确保Hibernate对CockroachDB有一流的支持,并且我们可以解决一些不太常用的Postgres兼容性问题,这些问题没有出现在我们的路线图中。

这就是为什么在改进SQL兼容性的同时,我们决定创建自己的Hibernate方言。CockroachDB Hibernate方言允许我们通过引入特定于CockroachDB的语义来提供更好的开发体验。与Postgres方言相比,CockroachDB方言可以自动处理丢失的BLOB存储和标识列支持。

我们与Hibernate维护者一起工作,从5.4.19版开始,CockroachDB方言是正式Hibernate发行版的一部分。展望未来,我们的团队还将有机会使用CockroachDB特定的特性进一步扩展CockroachDB方言。因为该方言在主要的Hibernate Repo中,所以它将被永久维护,并且集成到Hibernate的主要版本中可以帮助我们提供更好的持续支持。感谢Hibernate团队为帮助我们完成合并所做的所有辛勤工作!

除了Hibernate之外,我们还在CockroachDB中实现了对ActiveRecord(Ruby)、SQLAlChemy(Python)、GORM(GO)和TypeORM(TypeScript)的支持。这里提供了CockroachDB支持的ORM和其他第三方数据库工具的完整列表。想要使用另一个ORM吗?我们可能已经在做这件事了。您可以首先在我们的问题跟踪器中搜索ORM。如果您发现相关问题,请通过GitHub的反应表达您的支持。

非常感谢添加ORM相关特性的拉请求。CockroachDB Core是开源的,并从社区拉取请求中获益良多。如果这不可行,请提交一个包含使用ORM的测试脚本或单元测试的问题。如果我们不需要首先投资于理解支持及其不兼容性,那么就更容易确定支持的优先顺序。

如果您想使用Hibernate ORM和CockroachDB构建应用程序,那么现在就开始使用Hibernate构建一个Java应用程序。