环境: Spring应用程序,使用JOOQ 3.7,使用Postgres作为我的数据库,自动从模式生成JOOQ映射代码。
我一直在将一些代码从Hibernate移植到JOOQ。 Hibernate代码在每个上下文的基础上提取一些身份验证细节,以填充“createdBy”,“updatedBy”,日期等字段。
目前我可以通过JOOQ看到这样做的唯一方法是开发人员必须记住编写代码以便每次更新对象时手动更新字段,我可以看到它会变得单调乏味且容易忘了填充田地。
使用JOOQ,我是否有办法以更好的方式处理每个表上的“历史字段”,而不是手工编写一堆代码?
我们目前不使用DAO,我宁愿避免编写/生成整个代码层来处理这些历史字段。
另一种选择可能是在数据库中执行此操作,如果JOOQ无法帮助解决问题,那么很可能就是我们要做的。
答案 0 :(得分:6)
使用jOOQ有几种方法可以做到这一点:
RecordListener
在UpdatableRecord
每次调用以下任何一个时都会调用RecordListener
SPI:
TableRecord.insert()
UpdatableRecord.store()
UpdatableRecord.update()
UpdatableRecord.delete()
UpdatableRecord.refresh()
但是,在编写明确的DML语句时,不会调用此SPI。有关详细信息,请参阅手册,此处:
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:
我认为最好的解决方案是使用触发器将这种自动生成的数据移动到数据库中。这将允许您在迁移,手动更新或通过Java之外的其他语言(例如Perl脚本等)进行迁移时更新这些值
jOOQ 3.10还有待处理的功能请求:
它将精确实现此功能,以及其他一些不错的补充,例如二维版本控制:
答案 1 :(得分:2)
有趣的问题。我想说你有两种方法。
复制Hibernate方法。您可以将自定义操作绑定到executeEnd步骤。这是在进入行之后发生的。您可以访问query对象。基于此,您可以尝试找出如何在单独的调用中更新这两个字段(创建/修改)。您可能希望在使用executeStart执行数据库之前扩充查询,但这将是棘手的。
设计。如果你不想创建样板代码,那很好,但有没有理由你不能创建一些对象来处理这个前/后处理?您可以通过一些智能代理来驱动您的查询,该代理将为您更新记录。也许在数据库中创建一些历史表是一个好主意,它不仅要记住修改时间,还要记住已完成/更改的内容。你不再使用hibernate了。你不仅限于它给你的东西:)。