JOOQ - 相当于用于填充历史字段的休眠拦截器?

Posted

技术标签:

【中文标题】JOOQ - 相当于用于填充历史字段的休眠拦截器?【英文标题】:JOOQ - equivalent of hibernate interceptor for populating history fields? 【发布时间】:2016-02-05 17:10:55 【问题描述】:

环境: Spring 应用程序,使用 JOOQ 3.7,从模式中自动生成 JOOQ 映射代码,使用 Postgres 作为我的数据库。

我一直在将一些代码从 Hibernate 移植到 JOOQ。 Hibernate 代码会根据上下文提取一些隐藏的身份验证详细信息,以填充“createdBy”、“updatedBy”、日期等字段。

目前我认为使用 JOOQ 执行此操作的唯一方法是开发人员必须记住每次更新对象时都必须编写代码来手动更新字段,我可以看到这将变得乏味且容易忘记填充字段。

使用 JOOQ,有什么方法可以比手动编写一堆代码更好地处理每个表上的“历史字段”?

我们目前不使用 DAO,我宁愿避免编写/生成一整层代码来处理这些历史字段。

另一种选择可能是在数据库中执行此操作,如果 JOOQ 无法解决问题,我们可能会这样做。

【问题讨论】:

【参考方案1】:

使用 jOOQ 有几种方法可以做到这一点:

1。使用RecordListenerUpdatableRecord 上生成这些值

RecordListener SPI 会在您每次调用以下任意项时被调用:

TableRecord.insert() UpdatableRecord.store() UpdatableRecord.update() UpdatableRecord.delete() UpdatableRecord.refresh()

但是,当您编写显式 DML 语句时,不会调用此 SPI。有关详细信息,请参阅此处的手册:

http://www.jooq.org/doc/latest/manual/sql-execution/crud-with-updatablerecords/crud-record-listener

2。使用VisitListener转换jOOQ生成的所有SQL语句

VisitListener SPI 可用于任意 SQL 转换操作。您可以拦截 jOOQ 生成的各种 SQL 语句,并为其添加附加子句,例如

UPDATE table SET a = 1, b = 2 WHERE id = 3

会变成

UPDATE table SET a = 1, b = 2, updatedBy = 'me' WHERE id = 3

此 SPI 记录在手册中:

http://www.jooq.org/doc/latest/manual/sql-building/queryparts/custom-sql-transformation

3。编写触发器

我认为最好的解决方案是使用触发器将这种自动生成的数据移动到数据库中。这将允许您在迁移、手动更新或通过 Java 以外的其他语言(例如 Perl 脚本等)访问时更新这些值

4。等待 jOOQ 3.10

jOOQ 3.10 有一个待处理的功能请求:

https://github.com/jOOQ/jOOQ/issues/1592

它将精确地实现此功能,以及其他一些不错的附加功能,例如二维版本控制:

https://github.com/jOOQ/jOOQ/issues/4704

【讨论】:

2 在短期内看起来很有希望。对于 3,JOOQ 将用户 ID 传递给数据库的最佳方式是什么? (也许这应该是一个单独的问题) @Shorn:是的,一个单独的问题会很有趣!这取决于数据库和您的架构。它可能是数据库用户本身,或者您可以在使用 SYS_CONTEXT 或等效的东西从连接池(例如在 Oracle 中)获取连接时初始化连接【参考方案2】:

有趣的问题。我会说你在这里有两种方法。

    复制休眠方法。您可以将自定义操作绑定到executeEnd 步骤。这是在进入行后发生的。您可以访问query 对象。基于此,您可以尝试弄清楚如何在单独的调用中更新这两个字段(创建/修改)。您可能还想在使用 executeStart 对数据库执行之前增加查询,但这会很棘手。

    设计。如果您不想创建样板代码,那很好,但是您是否有理由无法创建一些将为您处理此预处理/后处理的对象?您可以通过一些将为您更新记录的智能代理来驱动您的查询。也许在数据库中创建一些历史表是个好主意,它不仅要记住修改时间,还要记住已经完成/更改的内容。你不再使用休眠。你不仅限于它给你的东西:)。

【讨论】:

我喜欢 2)。触发器生成的审计表可以成为很好的历史记录工具

以上是关于JOOQ - 相当于用于填充历史字段的休眠拦截器?的主要内容,如果未能解决你的问题,请参考以下文章

Dropwizard休眠字段未填充

从休眠审计历史中选择一个字段

JOOQ 与休眠行为

Hibernate 和 jOOQ 共享事务

用于从表中选择具有最新时间戳的行的 JOOQ 代码

setFixedCHAR() 是不是在 JOOQ 中实现