介绍Hrorm:一个简单的,声明式的,经过类型检查的ORM

一个问题

关于将Java代码中的模型与关系(SQL)数据库中的模型连接的问题,已经有很多网络墨水泄露了。对象关系映射(ORM)的主题确实很丰富,您可能想要在应用程序和数据库之间传输信息的全部内容都是巨大的。许多ORM工具试图覆盖尽可能多的空间; 他们的设计和实现提供了很大的灵活性,并且具有丰富的功能。

当然,为了实现这种灵活性,他们背负着复杂性。这不是他们的错:Java和SQL是完全不同的世界,涵盖所有(甚至许多)将它们组合在一起的方法本质上是复杂的。不同的方法呢?如果不是设计一个ORM工具来处理各种各样的对象和模式模型以及所有相关的用例,那么ORM工具的设计考虑了一些关于对象和模式的外观和工作方式以及如何使用它们的假设?ORM工具有多简单?

JDBC

Java数据库连接(JDBC)API定义了关系数据库和Java应用程序之间几乎所有交互的发生。数据库制造商提供了java.sql包中定义的接口的实现,客户端可以通过这些接口执行许多数据库任务,几乎除了实际启动数据库之外的所有内容。

在大大过量的简化方面,JDBC定义三个接口:java.sql.Connectionjava.sql.Statement,和java.sql.ResultSet。A Connection表示应用程序和数据库引擎之间的管道或套接字。形式的消息Strings可以使用a Statement和从中读取的响应传递给管道ResultSet

JDBC是一个低级接口,但它实际上只指定了应用程序和数据库之间的交互方式,因为它不会对发送到数据库的SQL采取什么形式。您可以使用JDBC将任意SQL字符串发送到数据库。假设它甚至是SQL,完全由数据库来解析和执行它。因此,只要它们符合接受查询作为SQL字符串并使用表格数据进行响应的基本模式,JDBC就支持提供具有完全不同扩展的SQL方言的数据库。

这取决于你如何看待它,这使得JDBC非常强大(几乎可以做任何事情)或非常贫穷(抽象不适合高级编程)。但从理论上讲,只需使用JDBC接口,就可以管理Java应用程序需要与关系数据库进行的几乎任何交互。它可能需要大量重复的代码才能实现。

代码的重复性质不容小觑。首先,您必须自己编写所有SQL,通常作为文字字符串。JDBC没有提供任何帮助。另外,SQL的语法稍有不同意味着所有选择,插入,更新和删除都必须分别写入某种程度。然后,每个必须在a Connection内传递,Statement并且ResultSet(如果相关)处理略有不同。然后,必须将结果解析为应用程序的对象模型。在整个过程中,必须注意正确地释放资源,以免数据库耗尽连接或游标或者你拥有什么。当然,即使是close()所有方法也都会检查SQLException所以一切都必须包含在(可能是嵌套的)try-catch-finally块中。所有这一切都在加入之前以及其他可能优化的整个世界之前都已经考虑过了。

编写这些繁琐的代码并且不可避免地会出现剪切和粘贴错误 - 或者更糟糕的是 - 最终导致任何人的工作。

奥姆斯

因此,使用ORM的主要原因之一就是避免编写和维护直接使用JDBC所需的所有样板代码。如果你有一支低薪,无耻的实习生,你可能永远都不会打扰。

JDBC是数据库概念的直接建模,如Java类和接口。因此,除了非常详细之外,产生的代码有点笨拙。改善问题的一种方法是为客户提供更现代,惯用的课程。像JDBI这样的库采用这种方法。事实上,JDBI网页声称它不是ORM,因为它不提供缓存或状态跟踪等等。它仍然需要开发人员自己编写SQL。尽管如此,与原始JDBC相比,它大大减少了包含的代码应用程序的数量。有时,JDBI被称为“更好的JDBC”。

其他ORM(假设我们可以将JDBI称为ORM,意味着对作者没有冒犯)在管理应用程序如何管理与数据库的交互方面有更多的抱负。Java ORM工具的祖父是Hibernate,它实际上帮助定义了javax.persistence包的构建方式。

Hibernate现在是一个广泛的工具生态系统,远远超出了减少直接使用JDBC编写应用程序所需的样板代码的最初目标。有关于Hibernate的教程和文档以及会议和书籍。而对于一些人来说,这本身就是问题所在。最开始的大量重复代码被削减到大小的直接问题现在本身就是一个完整的领域问题,需要投入时间和研究。学习所有关于Hibernate的知识大概都有自己的奖励,但它确实带来了(至少)两个问题。首先,Hibernate的强大功能和灵活性意味着即使是简单的东西实际上也很复杂。当您不需要缓存时,可能会引入意外的行为,如缓存。第二,当需要进行一些优化(将查询提示传递给DB,以特定方式创建连接等)时,很难知道如何让Hibernate与这种努力合作。您可以直接将SQL字符串传递给数据库的日子已经一去不复返了。

介绍Hrorm

对于许多项目,可以使用一对一的表存储来支持类似Java-bean的域模型。Hrorm是一个库,可以轻松创建数据访问对象(DAO),这些对象可以为Java-bean类执行基本的CRUD操作。它对您的对象模型和模式的设计有一些限制,并且在从您的应用程序与数据库进行通信时,它不会执行您可能想要的所有操作,但您不必将O'Reilly图书库投资到用它。

Hrorm允许轻松创建Dao<T>对象,允许您插入,选择,更新和删除类型的实例T。要创建Dao对象,请使用DaoBuilder类,该类提供声明性,流畅,类型安全的接口,用于描述数据库模式和Java对象模型之间的关系。具有以下成分域模型的应用程序:

    class  Ingredient {
        //省略了getter和setter,用你的想象力
        长 ID ;
        long  recipeId ;
        字符串 名称 ;
        int  金额 ;
    }

这是由数据库表支持的,如下所示:

    桌子成分(
        ID INTEGER PRIMARY KEY,
        RECIPE_ID INTEGER,
        NAME VARCHAR,
        AMOUNT INTEGER
    );

可以通过Dao像这样创建的Hrorm 来管理它的持久性:

    DaoBuilder < Ingredient >  ingredientDaoBuilder  =  new  DaoBuilder <>(“INGREDIENT”,Ingredient :: new)
        。withPrimaryKey(“ID”,“INGREDIENT_SEQUENCE”,Ingredient :: getId,Ingredient :: setId)
        。withParentColumn(“RECIPE_ID”)
        。withStringColumn(“NAME”,Ingredient :: getName,Ingredient :: setName)
        。withIntegerColumn(“AMOUNT”,Ingredient :: getAmount,Ingredient :: setAmount);

使用DaoBuilder和java.sql.Connection对象,您可以Dao像这样创建一个。

    Dao < Ingredient >  ingredientDao  =  ingredientDaoBuilder。构建(连接);

我们已经完成了。没有写SQL。没有异常处理或资源管理。没有迭代结果。只是简单的Dao<T>对象,有做标准的CRUD操作的方法insert()update()以及delete()对类型的对象行为T。此外,有多种select()方法可以从数据库中读取返回单个T实例的数据List<T>

对于如何设计与Hrorm一起使用的域模型存在一些限制。例如,实体必须具有整数(以Java术语表示   long )有价值的主键,并且主键必须从Hrorm可以访问的数据库序列生成。

要说Hrorm的全部内容都是不真实的。还有一些需要学习的内容,主要是关于如何处理代码和模式中的一对一和多对一关系。您可以在Hrorm文档中阅读相关内容。但实际上,您已经了解了开始使用Hrorm时需要了解的大部分内容。它是一个库,而不是一个框架:它不需要任何配置,具有任何外部依赖性,启动任何后台线程,或者使用注释污染您的域模型。

而且由于Hrorm只需要一个标准的JDBC Connection对象,因此很容易超出。您可以Dao使用自定义优化代码逐个替换Hrorm生成的对象,并且仅在必要时替换。由于Hrorm对其实现采用了一种准功能方法(没有隐藏的缓存或状态跟踪),因此调试没有令人费解的行为。调用Hrorm方法会导致SQL在调用线程上发送到数据库。

Hrorm甚至没有尝试管理您可能想要对数据库或应用程序执行的全部操作。但是它很快就能让你的对象保持最低限度。对于我们中的许多人来说,现代ORM工具以我们不需要付出的代价提供我们不需要的功能。

猜你喜欢

转载自blog.csdn.net/Tybyqi/article/details/86159420
今日推荐