SELECT * FROM T_AUTHOR WHERE ROWNUM <= 1 FOR UPDATE OF FIRST_NAME,LAST_NAME WAIT 5
完整的FOR UPDATE子句语法规范(至少对于Oracle)可以在这里看到:
FOR UPDATE [ OF [ [ schema. ] { table | view } . ] column [,[ [ schema. ] { table | view } . ] column]...] [ { NOWAIT | WAIT integer | SKIP LOCKED } ]
http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/img_text/for_update_clause.htm
使用jOOQ,我真的希望接近sql语法.所以我希望能够使用jOOQ流畅的API对上面的sql子句进行建模,如下所示:
Result<Record> result = create.select() .from(T_AUTHOR) .limit(1) .forUpdate() .of(FIRST_NAME,LAST_NAME) .wait(5) // Here's the issue .fetch();
fetch方法用于将API的底层对象呈现为sql,并针对Oracle(或任何其他)数据库运行sql语句.以上内容可以在界面中合法指定:
/** * A type that models a "step" in the creation of a query using the fluent API */ public interface SelectForUpdateWaitStep extends SelectFinalStep { // [...] /** * Add a "FOR UPDATE .. WAIT n" clause to the query */ SelectFinalStep wait(int seconds); // [...] }
不过,我对此有一些疑问,因为存在与另一种方法发生冲突的风险:
public class Object { // [...] public final native void wait(long timeout) throws InterruptedException; // [...] }
多亏了方法重载(int与长参数),我实际上可以做到这一点.但我担心它可能会让我的用户感到困惑并导致错误.所以这是错的:
.forUpdate() .of(FIRST_NAME,LAST_NAME) .wait((long) 5) // This doesn't make sense .fetch(); // This doesn't compile
所以我的问题是:
>我可以以某种方式阻止调用/访问Object.wait(long)altoghether?我不这么认为,因为它被宣布为最终,但也许有人知道编译器技巧,或其他什么?
>除了将方法重命名为doWait(int)或WAIT(int)之类的东西之外,您对我的API设计有更好的想法吗?
解决方法
起初,这与继承的整个概念相矛盾 – 一旦从类继承,所有子类必须暴露相同的非私有字段&方法.您始终可以覆盖方法,除非(1)它被标记为final,(2)它具有不兼容(非协变)返回类型,这两种方法都适用于void wait(long)方法.
此外,由于每个对象都是Java中的Object,所以一切都必须有一个方法void wait(long),并且无法隐藏/删除/禁用/转发/覆盖它.假设有可能隐藏void wait(long)方法,如果你想调用它,你将如何调用它?
但是,假设您永远不需要为特定类调用void wait(long),那么AspectJ总是采用源/字节代码编织的方法,以便根据某些调用规则更改.class Java字节码.您可以捕获每个等待(长)的调用并声明错误/警告.在这里查看更多:http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations-decp.html
但是,即使使用带字节码编织的AspectJ,也无法使用本机方法切入点.最有可能的是,即使使用源代码编织也无法做到这一点 – 但它可能值得一试.