【问题标题】:Avoiding casts when narrowing jooq selects缩小 jooq 选择时避免强制转换
【发布时间】:2019-08-09 17:57:14
【问题描述】:

假设我有一个图书数据库,我想检查 CLRS 图书的作者是否正确。

假设private static final String CLRS_title = "Introduction to Algorithms";

    @Test
    public void CLRS_is_written_by_CLRS(){
        //given        
        SelectConditionStep<Record> query = create
                .select()
                    .from(
                            (
                                    BOOK.leftOuterJoin(BOOK_AUTHOR).on(BOOK.ID.eq(BOOK_AUTHOR.BOOKID))
                            ).leftOuterJoin(AUTHOR).on(AUTHOR.ID.eq(BOOK_AUTHOR.AUTHORID))
                    )
                    .where(BOOK.TITLE.eq(CLRS_title))
                ;

        //when
        Result<Record> result = query.fetch();
        List<String> authorNames = result.stream().map(r-> r.getValue(AUTHOR.LASTNAME)).collect(Collectors.toList());

        //then
        assertThat(authorNames.size(),is(4));
        assertThat(authorNames.containsAll(Arrays.asList("Cormen","Leiserson","Rivest","Stein")), is(true));

    }

(请忽略,当我们只对一本书感兴趣时,加入整个表格是非常低效的,如果/必要时,我会提出一个单独的问题。)

我现在只想选择 AUTHOR.LASTNAME 属性而不是全部。

SelectConditionStep<Record1<String>> query = create
        .select(AUTHOR.LASTNAME.as("AuthorName"))
            .from(
                    (
                            BOOK.leftOuterJoin(BOOK_AUTHOR).on(BOOK.ID.eq(BOOK_AUTHOR.BOOKID))
                    ).leftOuterJoin(AUTHOR).on(AUTHOR.ID.eq(BOOK_AUTHOR.AUTHORID))
            )
            .where(BOOK.TITLE.eq(CLRS_title))
        ;

//when
Result<Record1<String>> result = query.fetch();
List<String> authorNames = result.stream().map(r-> (String)r.getValue("AuthorName")).collect(Collectors.toList());

//then
assertThat(authorNames.size(),is(4));
assertThat(authorNames.containsAll(Arrays.asList("Cormen","Leiserson","Rivest","Stein")), is(true));

需要在authorNames 生成中转换为String,因为没有它,我无法编译,因为

不兼容的类型。必需的列表,但“收集”被推断为 R:不存在类型变量的实例,因此 Object 符合字符串推断变量 T 具有不兼容的边界:等式约束:字符串下限:对象

有没有办法避免这种强制转换并仍然获得更窄的选择?

【问题讨论】:

  • 天哪!这段代码看起来就像只为一个字节制作卷饼! @User1291
  • @MS90 谢谢你的笑声。 :) 我正在尝试进入 JOOQ,因此查询可能比严格必要的要复杂一些。 (例如,我知道我们可以取消 BOOK 表上的整个连接,但是当我们不假设我们知道 ID 为 1 时,这是必要的)。
  • 没问题,你能告诉我你想做什么吗,一步一步的方法最好一起做。
  • 好吧,我有 BookAuthorBook_Author 表。 Books 和 Authors 有 ID,Book_Author 包含从 Book.IDs 到 Author.IDs 的映射。因此,查询将BookBook_Author 表连接起来,然后将结果表与Author 表连接起来,使用ID 将它们联系在一起。然后我们选择我们想要的书并获得该书所有作者的姓氏。我现在想把SELECT * 变成SELECT author.lastname as AuthorName,这就是第二个版本所做的。但这样做需要我从Record 更改为Record1&lt;String&gt; 和...
  • ... 这反过来又要求我在将名称提取到 authorNames 列表时插入 (String)。我现在想摆脱那个演员。 @MS90

标签: java sql select casting jooq


【解决方案1】:

没有别名

我不明白您为什么要重命名您的专栏。就……

.select(AUTHOR.LASTNAME)

然后

List<String> authorNames = result.getValues(AUTHOR.LASTNAME);

带别名

如果您必须给它起别名,那么它有助于将别名列表达式分配给局部变量:

Field<String> lastname = AUTHOR.LASTNAME.as("lastname");

// ...
.select(lastname)

...然后:

List<String> authorNames = result.getValues(lastname);

或者,您可以重复别名表达式两次

.select(AUTHOR.LASTNAME.as("lastname"))

...然后:

List<String> authorNames = result.getValues(AUTHOR.LASTNAME.as("lastname"));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-06
    • 1970-01-01
    相关资源
    最近更新 更多