【问题标题】:Forced PostgreSQL type convertion using JOOQ tool使用 JOOQ 工具强制 PostgreSQL 类型转换
【发布时间】:2018-11-30 11:28:24
【问题描述】:

有没有办法配置 JOOQ 工具,使用 PostgresSQL 数据库的“forcedTypes”标签将 smallint 转换为 Boolean,而不提供 org.jooq.Converter 实现?

这是当前配置的样子:

<forcedTypes>
    <forcedType>
        <name>BOOLEAN</name>
        <types>smallint.*</types>
    </forcedType>
<forcedTypes>

正在使用 JOOQ v3.9.1。 PostgreSQL v9.6.6。

不幸的是,在将信息存储到数据库中时收到了下一个异常:

Caused by: org.postgresql.util.PSQLException: ERROR: column "is_complete" is of type smallint but expression is of type boolean

还尝试使用 MySQL 数据库,从 tinyint 到 Boolean 的类似转换工作正常,没有任何错误:

<forcedTypes>
    <forcedType>
        <name>BOOLEAN</name>
        <types>tinyint.*</types>
    </forcedType>
</forcedTypes>

【问题讨论】:

  • 它在 MySQL 中有效,因为 MySQL 实际上没有布尔数据类型。 boolean 只是那里的tinyint 的别名
  • 好的,那么 PostgresSQL 会出现什么问题,因为我使用的是 smallint 而不是纯布尔类型? smallint 和 tinyint 的外观非常相似
  • 如果你想要一个布尔值,那么你为什么不使用boolean
  • 是的,不幸的是需要使用一个现有的数据库,其中布尔值存储为小整数:)

标签: postgresql type-conversion jooq


【解决方案1】:

不,这不符合您的预期(而且不应该)。在 jOOQ 中,如果数据库支持,BOOLEAN 数据类型将作为本机 BOOLEAN 类型绑定到 JDBC,例如PostgreSQL。

如果数据库不支持该类型(例如 MySQL / Oracle),那么 jOOQ 将绑定 0/1/NULL 数值。但是您不能对原本支持BOOLEAN 类型的方言强制执行此行为。但是话又说回来,为什么不写那个转换器呢?这真的很简单。只需添加:

<forcedTypes>
    <forcedType>
        <userType>java.lang.Boolean</userType>
        <converter>com.example.BooleanAsSmallintConverter</converter>
        <!-- A bit risky. Are all smallints really booleans in your database? -->
        <types>smallint.*</types>
    </forcedType>
<forcedTypes>

然后:

class BooleanAsSmallintConverter extends AbstractConverter<Short, Boolean> {
    public BooleanAsSmallintConverter() {
        super(Short.class, Boolean.class);
    }

    @Override
    public Boolean from(Short t) {
        return t == null ? null : t.shortValue() != (short) 0;
    }

    @Override
    public Short to(Boolean u) {
        return u == null ? null : u ? Short.valueOf((short) 1) : Short.valueOf((short) 0);
    }
}

【讨论】:

    【解决方案2】:

    你可以这样做,但我怀疑这就是你的想法。您必须在 PostgreSQL 中创建 custom cast

    CREATE FUNCTION bool2int2(IN bool, OUT int2)
    LANGUAGE SQL
    AS $$
    SELECT CASE WHEN $1 THEN 1::int2 WHEN $1 IS NOT NULL THEN 0::int2 END
    $$;
    
    DROP CAST IF EXISTS (bool AS int2);
    CREATE CAST (bool AS int2)
    WITH FUNCTION bool2int2(bool)
    AS ASSIGNMENT;
    

    那么这将起作用:

    DROP TABLE IF EXISTS booltest;
    CREATE TABLE booltest (id serial, boolval int2);
    INSERT INTO booltest (boolval) VALUES(true),(false),(null::bool);
    SELECT * FROM booltest;
     id | boolval
    ----+---------
      1 |       1
      2 |       0
      3 | (null);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-25
      • 2021-12-16
      • 2016-09-04
      • 2014-02-16
      • 2021-11-15
      • 2021-01-24
      • 2014-07-21
      • 2015-12-17
      相关资源
      最近更新 更多