26

偶然发现了一个不错的 SQL 构建器框架,称为JOOQ。顺便说一句,在俄语 JOOQ 中听起来像名词,意思是“虫子”(作为昆虫)、“甲虫”;)

如果您对 JOOQ 有任何反馈,它的性能等,请分享。也欢迎链接到有关 JOOQ 的博客。

4

3 回答 3

32

我想我也应该在这里回答,因为我在一个半月前开始使用 jooq,所以我有一些经验。

我想使用像 jooq 这样的工具,因为:

  • 在我当前的项目(集群的分布式计算平台)中,ORM 是一种过度杀伤力,因为我只需要从 db 中读取和写入单独的字段,而不是完整的表行,而且我的一些查询非常复杂,无法由简单和轻量级的 ORM 执行。
  • 我想要查询的语法自动完成,这样我就不需要记住我的整个数据库
  • 我希望能够直接用 Java 编写查询,以便编译器可以在构建时检查基本查询语法。
  • 我希望我的查询是类型安全的,这样我就不会意外地传递一种类型的变量,而需要另一种类型的变量。
  • 我想要 SQL,但我想要它非常方便和易于使用

好吧,有了 jooq,我就能做到这一切。我的主要要求是让 jooq 处理足够复杂的查询(嵌套、分组等)。那实现了。

我还希望能够使用尽可能少的代码行来运行查询,并且能够使用 jooq fluent API 来实现这一点,该 API 允许类似 jquery 的调用来执行 SELECT。

在我使用 jooq 的过程中,我报告了一两个错误,我必须说,它们修复得非常快。

我也错过了一些功能,我必须再说一遍,我几乎已经拥有了所有这些功能。

我非常喜欢的是,jooq 现在使用 SLF4J 来报告一些非常有趣的关于其性能的数据以及输出它所构建的实际查询。它真的帮助我调试。

Jooq 甚至为存储过程、UDF 和可更新记录集生成 Java 工件,但我目前不使用它们。

重要的是,jooq 透明地支持 DB2、Derby、H2、HSQLDB、MySQL、Oracle、PostGreSQL、SQLite、SQL Server、Sybase SQL Anywhere。相当广泛的清单,我想。

Jooq在 Google 群组中有支持论坛,Lukas 日夜准备回答我最愚蠢的问题。

Jooq 支持 Maven,这让我松了一口气,因为我所有的 Java 项目都是基于 Maven 的。我们仍然想念生成器的 Maven 插件,但这并不重要,因为运行生成器是小菜一碟。

使用 jooq 编写查询时,我突然发现,它们变得非常可移植,因为我几乎从未在代码中使用任何 MySQL 特定的功能,因为 jooq 试图尽可能地便携。对于那些不能忍受这些特性的人,据我所知,对 SQL 扩展的支持也在进行中。

在我看来,jooq 暂时缺少什么?

好吧,除了 SELECT 之外,没有用于语句的流畅 API。这会使代码稍微复杂化,并使 UPDATE/DELETE 语句的编写更加复杂。但我认为这将很快添加。刚刚在 1.5.9 中实现!哈!对我来说太快了;)

还有一件事情。Jooq 有一本很好的手册,但是……我不知道。可能我只是不明白它的结构或架构......当我第一次开始使用jooq时,我打开一个又一个页面寻找我需要的功能。例如,尝试猜测,在jooq 手动UPDATE 和 DELETE 语句中描述的位置,查看内容......但这真的很主观,我相信。我什至无法解释,从我的角度来看,手册有什么问题。如果可以的话,我会张贴一两张票;)

手动也不是很好导航,因为 Trac 没有类似“这里、那里和返回”的自动链接。

好吧,对我来说,在莫斯科(俄罗斯)的 Trac 页面打开速度也不快,所以阅读手册有点无聊。

手册还缺少对贡献者的 jooq 的良好架构描述。Jooq 似乎遵循按合同设计的原则,当我想通过在 IDE 中使用我通常的 Ctrl-Click 某个方法名称来了解如何在内部实现某些功能时,我最终进入了一个没有实现的沉闷界面;)不是这样我太聪明了,无法立即开始改进 jooq,但我当然会喜欢了解 jooq 是如何从头到尾构建的。

也很遗憾我们不能为 jooq 手册做出贡献。我希望它出现在某种 wiki 中。

我还想改进的是新闻报道的方式 。我更喜欢那里的手册链接或这个或那个新功能如何工作的示例。

手册中的发行说明链接实际上只是一个路线图。我想,我明天会自己做那个……

Jooq 目前也有相对较小的社区,但我很高兴地报告它不会影响代码质量或引入新功能的方式。

Jooq 确实是一个很好的项目。我也会在我未来的项目中坚持下去。我很喜欢。

于 2011-05-15T22:08:54.530 回答
2

您还可以查看MentaBean,这是一个轻量级的 ORM 和 SQL Builder,它可以让您尽可能接近 SQL,为样板代码提供大量帮助。这是一个例子:

编程配置:

private BeanConfig getUserBeanConfig() {

    // programmatic configuration for the bean... (no annotation or XML)

    BeanConfig config = new BeanConfig(User.class, "Users");
    config.pk("id", DBTypes.AUTOINCREMENT);
    config.field("username", DBTypes.STRING);
    config.field("birthdate", "bd", DBTypes.DATE); // note that the database column name is different
    config.field("status", new EnumValueType(User.Status.class));
    config.field("deleted", DBTypes.BOOLEANINT);
    config.field("insertTime", "insert_time", DBTypes.TIMESTAMP).defaultToNow("insertTime");

    return config;
}

   // create table Users(id integer primary key auto_increment, 
   // username varchar(25), bd datetime, status varchar(20), 
   // deleted tinyint, insert_time timestamp)

一个简单的 SQL 连接查询:

Post p = new Post(1);

StringBuilder query = new StringBuilder(256);
query.append("select ");
query.append(session.buildSelect(Post.class, "p"));
query.append(", ");
query.append(session.buildSelect(User.class, "u"));
query.append(" from Posts p join Users u on p.user_id = u.id");
query.append(" where p.id = ?");

stmt = conn.prepareStatement(query.toString());
stmt.setInt(1, p.getId());

rset = stmt.executeQuery();

if (rset.next()) {

    session.populateBean(rset, p, "p");

    u = new User();

    session.populateBean(rset, u, "u");

    p.setUser(u);
}
于 2011-09-24T19:43:53.543 回答
0

如果您只寻找 SQL 构建器解决方案。我有一个项目,它是 Java 的 ORM 框架,但它仍然为时过早,并且在持续开发中,但是可以处理数据库的许多原始用法。https://github.com/ahmetalpbalkan/orman

此阶段没有文档,但是它可以仅使用 Java 链方法构建安全查询,并且可以处理许多 SQL 操作。它还可以将类字段分别映射到表列。

这是查询的示例查询构建操作

SELECT COUNT(*) FROM sailors WHERE
    rating>4 AND rating<9 GROUP BY rating HAVING AVG(age)>20;

Java代码:

    QueryBuilder qb = QueryBuilder.getBuilder(QueryType.SELECT);
    System.out.println(qb
            .from("sailors")
            .where(
                    C.and(
                            C.gt("rating", 5),
                            C.lt("rating", 9)))
            .groupBy("rating")
            .having(
                    C.gt(
                            new OperationalField(QueryFieldOperation.AVG,
                    "age").toString(), 20)
                    ).getQuery());

(哈哈,放弃开发那个框架吧!)

很可能这对你不起作用,但只是想宣布我的项目:P

于 2011-05-22T13:09:31.547 回答