背景:我使用jOOQ访问Firebird数据库。 Firebird 2.x的行大小限制为64KB。我以前从未达到过限制,但是这个特定的数据库使用UTF8,这意味着限制缩小到大约16K字符。
这就是我使用jOOQ的方式:
根据需要加载或创建POJO(生成)。例如:
Book book = context.fetchOne("select * from book where book_id = ?", 1).into(Book.class);
根据需要使用图书对象。
如果用户保存更改,则将其存储为记录。
BookRecord rec = context.newRecord(Tables.BOOK, book);
context.executeUpdate(rec);
步骤3在executeUpdate()
方法失败,因为某种方式jOOQ将所有空的VARCHAR
字段转换为VARCHAR(4000)
。错误消息是
" SQL错误代码= -204。超出实施限制。块大小 超出实施限制"。
这是一个已知的Firebird限制,遗憾的是没有任何关于它的事情。
在表格中,我有大约8个空VARCHAR(512)
字段,在UTF8中应该大约为8x4x512(或16KB),但是由于jOOQ将其解释为VARCHAR(4000)
,所以& #39; s 8x4x4000(128KB)显然超出限制。
如果我将NULL
或空字段设置为某个随机字符串,那么jOOQ会将其转换为精确的字符串长度。 (" ABC"将被投射到varchar(3)
)
所以我的问题是:如果没有jOOQ将我的空字段转换为executeUpdate()
,如何让VARCHAR(4000)
工作?
答案 0 :(得分:2)
这些演员阵容在jOOQ中具有历史意义,因为有些数据库很难单独从绑定变量推断数据类型,因为在查询执行之前它们不能延迟任何决策:
SELECT ? -- What's the type? Unknown at parse time.
这就是jOOQ为这些数据库生成显式强制转换的原因,其中包括Firebird:
SELECT cast(? as varchar(4000)) -- Now, the type is clear
目前,即使在语句/子句中也可以这样做,其中类型可以从上下文中推断出来,包括
INSERT INTO t(a, b) VALUES (?, ?)
-- ^ ^ | |
-- +--|----------+ |
-- +-------------+ Bind types can be inferred from column type
就Firebird而言,不幸的是,这种做法很快就会遇到上述尺寸限制。在jOOQ中有一些未决的功能要求可以改进这一点,但在jOOQ 3.9中尚未实现:
如果你想修改jOOQ,那么演员决定是在DefaultBinding.sql(BindingSQLContext)
。您将看到有几个选项如何覆盖当前行为:
Setting.paramCastMode == NEVER
关闭投射(可从jOOQ 3.10获取#1735)RenderContext.castMode()
以永远不会产生cast\(\?[^)]*\)
替换?
/api/v1/bars?page[size]=-1