Java:JOOQ 持久性框架性能和反馈 [已关闭]

2022-09-01 17:29:32

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

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


答案 1

我想我也应该在这里回答,因为我在一个半月前开始使用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页面也无法快速打开,因此阅读手册有点无聊。

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

同样遗憾的是,我们无法为jooq手册做出贡献。我期望它在某种wiki中。

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

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

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

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


答案 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);
}

推荐