当前位置: 首页 > 知识库问答 >
问题:

约克

湛博易
2023-03-14

背景:我正在使用jOOQ访问Firebird数据库。Firebird 2. x的行大小限制为64KB。我以前从未达到过限制,但是这个特定的数据库使用UTF8,这意味着限制缩小到大约16K个字符。

以下是我使用jOOQ的方式:

>

  • 根据需要加载或创建POJO(已生成)。例如。:

    Book book = context.fetchOne("select * from book where book_id = ?",  1).into(Book.class);
    

    根据需要使用book对象。

    如果用户保存更改,则将其存储回记录。

    BookRecord rec = context.newRecord(Tables.BOOK, book); 
    context.executeUpdate(rec);
    

    步骤3在executeUpdate()方法上失败,因为jOOQ不知何故正在将所有空的VARCHAR字段强制转换为VARCHAR(4000)。错误消息是

    “SQL错误代码=-204。超出了实现限制。块大小超出了实现限制”。

    这是一个已知的火鸟限制,不幸的是,对此无能为力。

    在表中,我有大约8个空的VARCHAR(512)字段,UTF8中的最大值应该是8x4x512(或16KB),但由于jOOQ将其解释为VARCHAR(4000),这就是8x4x4x4000(128KB),显然超出了限制。

    如果我将NULL或空字段设置为某个随机字符串,那么jOOQ会将其转换为精确的字符串长度。(“ABC”将被转换为varchar(3)

    所以我的问题是:我如何得到执行更新()工作,而不jOOQ铸造我的空字段到VARCHAR(4000)

  • 共有1个答案

    壤驷英叡
    2023-03-14

    这些强制转换在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中实现:

    • #1735添加设置以指示绑定值不应该被强制转换
    • #3398避免为Firebird中的每个bind变量长度生成新的SQL语句

    如果您想在您这边修补jOOQ,则在DefaultBinding.sql(BindingSQLContext)中做出强制转换决定。您将看到如何覆盖当前行为的几个选项:

    1. 关闭铸造与Setting.paramCastMode==从来(可从jOOQ 3.10与#1735)
    2. 重写RenderContext.cast模式()以始终产生永远不会
    3. 在自定义绑定中重写整个方法
    4. 修补逻辑,永远不要应用任何强制转换
    5. 实现一个ExecteListener,替换cast\(\?[^)]*\)by在您的SQL字符串
     类似资料:
    • 1.【强制】在表查询中,一律不要使用 *作为查询的字段列表,需要哪些字段必须明确写明。 说明: 1)增加查询分析器解析成本。 2)增减字段容易与resultMap配置不一致。 2.【强制】POJO类的boolean属性不能加is,而数据库字段必须加is_,要求在resultMap中进行字段与属性之间的映射。 说明:参见定义POJO类以及数据库字段定义规定,在sql.xml增加映射,是必须的。 3.

    • 1.【强制】不要使用count(列名)或count(常量)来替代count(),count()就是SQL92定义的标准统计行数的语法,跟数据库无关,跟NULL和非NULL无关。 说明:count(*)会统计值为NULL的行,而count(列名)不会统计此列为NULL值的行。 2.【强制】count(distinct col)计算该列除NULL之外的不重复数量。注意 count(distinctco

    • HTTP/1.0和HTTP/1.1 RFC7230:HTTP/1.1:消息语法和路由 RFC7231:HTTP/1.1:语义和内容 mitmproxy对HTTP/1.0和HTTP/1.1的支持基于我们的自定义HTTP堆栈,该堆栈负责所有语义和在线解析/序列化任务。 mitmproxy当前不支持解析HTTP预告片-但是,如果您想向我们发送PR,我们承诺一定要看一下! HTTP/2 RFC7540:超

    • 命名约定 在正式开始使用 LCUI 前,我们先了解一下 LCUI 的命名约定,这将有助于记忆和查找你需要的 API。 数据类型 大部分公共的数据类型都采用驼峰式命名法(Camel-Case),并带有 LCUI_ 前缀,像链表(LinkedList)、红黑树(RBTree) 和字典(Dict)这类基础数据类型,由于名称长度和可替代性,未加上 LCUI_ 前缀。 对于常以指针形态引用的数据类型,它的定

    • Solidity中合约有点类似面向对象语言中的类。合约中有用于数据持久化的状态变量(state variables),和可以操作他们的函数。调用另一个合约实例的函数时,会执行一个EVM函数调用,这个操作会切换执行时的上下文,这样,前一个合约的状态变量(state variables)就不能访问了。 创建合约 合约可以通过Solidity,或不通过Solidity创建。当合约创建时,一个和合约同名的

    • Solidity 合约类似于面向对象语言中的类。合约中有用于数据持久化的状态变量,和可以修改状态变量的函数。 调用另一个合约实例的函数时,会执行一个 EVM 函数调用,这个操作会切换执行时的上下文,这样,前一个合约的状态变量就不能访问了。 创建合约 可以通过以太坊交易“从外部”或从 Solidity 合约内部创建合约。 一些集成开发环境,例如 Remix, 通过使用一些用户界面元素使创建过程更加流