java 在jOOQ中,有没有一种方法可以保持列不可变(只允许插入)?

iyfjxgzm  于 11个月前  发布在  Java
关注(0)|答案(3)|浏览(87)

某些列的值只会被插入,永远不会被修改(实际上是复杂的外键,但由于各种原因没有Map)。在JPA中,这可以通过@Column(updatable=false)建模。
有没有一种方法可以在jOOQ中 * 系统地 *(而不是手动地)实现这一点?我知道read-only columns,但是不可变(只插入)的列似乎不存在。对吗?
我知道jOOQ在某些上下文中知道JPA注解,因为我大部分时间都使用生成的DAO,我想我仍然可以使用注解,但我宁愿不使用,因为我在项目的其他任何地方都不使用JPA。

2nc8po8w

2nc8po8w1#

@lance-java的触发器对于Postgres是完全无效的(可能是Oracle)。Postgres需要一个 * 返回trigger* 的函数和调用该函数的触发器定义。然而,这种方法是合适的;只需将新值替换为现有值(甚至没有理由查看值)。参见demo

create or replace function make_x_immutable() 
   returns trigger 
   language plpgsql
as $$
begin 
   new.x = old.x;
   return new;
end; 
$$;

create trigger  foo_bur
    before update on foo
    for each row 
    execute function make_x_immutable() ;

字符串

注意,旧版本的Postgres可能会在触发器定义上要求 *execute procedure... *。

c3frrgcw

c3frrgcw2#

下面是一个Oracle触发器,它可以忽略名为“foo”的表中“x”列的更新。

CREATE TRIGGER t_foo_bu
   BEFORE UPDATE ON foo
BEGIN 
   -- null safe equality check  
   IF NVL(new.x, chr(0)) != NVL(old.x, chr(0)) THEN
      DBMS_OUTPUT.PUT_LINE('Ignoring attempted update of foo.x from ' || old.x || ' to ' || new.x || ' for id ' || new.id); 
      new.x = old.x;
   END;
END;

字符串

oaxa6hgo

oaxa6hgo3#

只读列

从jOOQ 3.19开始,只有一个通用的readonly flag可以放在列上,而不是一个更具体的insertonlyupdateonly标志。这将是未来版本中的一个很好的功能:

但是,你可以在每个查询的基础上全局或局部地调用configure the above flag to apply only to INSERT or only to UPDATE statements。这将应用于查询中的所有列,而不仅仅是你想到的那些列,这对于INSERTUPDATE语句来说不是一个问题,但对于MERGE来说可能是一个问题。
这种方法既影响UpdatableRecord调用,也影响使用jOOQ DSL手动编写的查询。

录音

如果这只是关于UpdatableRecord交互,你可以实现一个RecordListener,它可以防止在UPDATE语句中包含某些列。这将影响所有UpdatableRecord.store()UpdatableRecord.update()调用,但不影响手动编写的查询。

SQL转换

您可以编写一个ExecuteListener,它可以非常容易地检查和修补Update.$set()列表。只需检查Update.$table()是否适用,然后检查Update.$set()是否包含“forbidden”列:
在您的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));
        }
    }
}

字符串

相关问题