使用 SimpleFlatMapper 更容易映射

Easier mapping with SimpleFlatMapper

jOOQ 可以自动为 select 子句中的 table 的所有列添加别名前缀吗?

jOOQ 也可以帮助解决数据库的 128 byte/character 名称长度限制吗?


问题的原因是SimpleFlatMapper用于映射。 SimpleFlatMapper 需要获取的数据库列名称映射到模型。

模型示例(真的getter/setter都在用):

class Head {
    public Integer id;
    public List<Position> positions;
    ...
}
class Position {
    public Integer id;
    public Integer headId;
    ...
}

命名可以单独完成:

ResultSet resultSet = dsl.select(..., POSITION.ID.as("positions_id"), ...)
    .from(HEAD)
    .join(POSITION.as("positions")).onKey()
    .fetchResultSet();
    
List<Head> headers = JdbcMapperFactory.newInstance()
                                      .ignorePropertyNotFound()
                                      .newMapper(Head.class)
                                      .stream(resultSet)
                                      .collect(Collectors.toList())

但是如果是复杂的模型有好几个joins/columns就有点乏味了。 我找到的唯一解决方案是手动编写一个函数。然而,我是否可能忽略了某些事情,而 jOOQ 可以自己完成或提供帮助?

这样的东西会很好(可能不是最好的命名,我当场想不出更好的东西):

ResultSet resultSet = dsl.select()
    .from(HEAD)
    .join(POSITION.as("positions").prefixColumns()).onKey()
    .fetchResultSet();

或者:

ResultSet resultSet = dsl.selectWithTableAlias()
    .from(HEAD)
    .join(POSITION.as("positions")).onKey()
    .fetchResultSet();

结果如下SQL:

SELECT head.id, head.***, positions.id AS positions_id, positions.headid AS positions_headid, positions.***
FROM head JOIN position AS positions ON head.id = positions.headid

此外,Oracle 和 MS 等数据库SQL 的名称限制为 128 bytes/characters。 在非常罕见的复杂场景中,由于需要嵌套,别名可能会达到该限制。

jOOQ 无法以某种形式为此提供解决方法,或者可以吗?所以基本上定义一个在 SQL 中使用的名称和一个实际结果对象的名称。

我知道,非常小众的要求。但是他们会对映射有很大帮助。

Can jOOQ automatically add an alias prefix for all columns of a table in the select clause?

没有这样的功能,因为所需的自动前缀算法的可能集非常大,jOOQ 最终不会 完全 你想要的。也许,将来 SPI 有空间帮助您执行此操作。但是还没有可用的:https://github.com/jOOQ/jOOQ/issues/11545

但是,您自己可以轻松地做到这一点,因为每个 jOOQ 查询只是一个动态构造的表达式树,即使您并不总是使用 jOOQ dynamic SQL

您可以轻松编写实用程序并在任何地方使用它:

public static List<Field<?>> autoPrefix(Field<?>... fields) {
    return autoprefix(Arrays.asList(fields));
}

public static List<Field<?>> autoPrefix(Field<?>... fields) {
    Stream.of(fields).map(f -> f.as(myPrefixLogic(f))).collect(toList());
}

这现在可以在所有 DSLContext.select() 调用中明确使用,例如

dsl.select(autoPrefix(..., POSITION.ID.as("positions_id"), ...))
    .from(HEAD)
    .join(POSITION.as("positions")).onKey()
    .fetchResultSet();

或者,您可以将查询包装在派生的 table:

public ResultSet fetchResultSetWithPrefix(Select<?> select) {
    Table<?> table = select.asTable("t");

    return
    dsl.select(autoPrefix(table.fields()))
       .from(table)
       .fetchResultSet();
}

现在,您不再调用 fetchResultSet(),而是调用您的辅助函数:

try (ResultSet rs = fetchResultSetWithPrefix(
    dsl.select(..., POSITION.ID.as("positions_id"), ...)
       .from(HEAD)
       .join(POSITION.as("positions")).onKey()
)) {
    ...
}

另一个更复杂的选择是使用 VisitListener

请记住,无论您的查询 看起来像什么(因为 jOOQ 的 DSL 在句法上模仿 SQL),所有 您的jOOQ 查询是 dynamic SQL queries,因此您可以相对轻松地将它们自动转换为您想要的任何内容。

Can jOOQ also help with the 128 byte/character name length limitation of databases?

对于这种自动化,我和以前一样持保留意见。你会在哪里看到 jOOQ 在这里提供自动帮助?鉴于您的命名方案 (table_column),您是否希望每个对象类型公平分配 63 个字符?或者 table 不如该列重要,您将截断 table 42 个字符的名称,为该列留下 85 个字符?

如果您想像 schema_table_column 那样完全限定标识符(包括架构名称)怎么办?如果您投射 UDT,这意味着您将获得 schema_table_column_attribute1_attribute2

我不认为 jOOQ 可以提供适合所有需求的任何自动化。但是,如上所示,只需为整个应用程序实现一次即可,确保始终正确应用命名非常简单。如果 SPI 可用,您可以在那里实现缩写逻辑。