从jOOQ 3.19版本开始,只有一种通用的readonly
标志可用于标记列,但并没有更具体的insertonly
或updateonly
标志。在未来版本中增加这样的特性会是一个不错的想法:
当前,你可以配置上述readonly
标志仅应用于INSERT
或仅应用于UPDATE
语句,这可以在全局范围内设置,也可以在每个查询的基础上局部设置。然而,这种方法会作用于查询中的所有列,而不只是你指定的特定列,这对INSERT
和UPDATE
语句可能不是问题,但对于MERGE
语句可能会产生问题。
这种做法会影响使用jOOQ DSL编写的查询以及UpdatableRecord
方法调用。
对于只想在UpdatableRecord
交互中限制某些列更新的情况,你可以实现一个RecordListener,它可以阻止在UPDATE
语句中包含特定列。这将影响所有的UpdatableRecord.store()
和UpdatableRecord.update()
调用,但不会影响手动编写的查询。
另外,你可以编写一个SQL转换器,即实现一个ExecuteListener,它能够简单地检查并修改Update.$set()列表。只需检查Update.$table()
是否适用,然后判断Update.$set()
是否包含了“禁止”的列。
在你的ExecuteListener.renderStart()实现中:
class NoUpdates implements ExecuteListener {
Set<Table<?>> tables = null;
Set<Field<?>> fields = null;
@Override
public void renderStart(ExecuteContext ctx) {
UnmodifiableMap<? extends FieldOrRow, ? extends FieldOrRowOrSelect> originalMap;
if (ctx.query() instanceof QOM.Update<?> u
&& tables.contains(u.$table())
&& (originalMap = u.$set()).keySet().stream().anyMatch(fields::contains)
) {
var newMap = new LinkedHashMap<>(originalMap);
var it = newMap.keySet().iterator();
while (it.hasNext()) {
if (fields.contains(it.next())) {
it.remove();
}
}
if (originalMap.size() != newMap.size()) {
ctx.query(u.$set(newMap));
}
}
}
}