Java 8 Friday:更多功能关系转换

过去,我们一直在每个星期五为您提供有关Java 8的新内容的新文章。这是一个非常令人兴奋的博客系列 ,但我们想再次将重点放在Java和SQL的核心内容上。 我们仍然偶尔会写关于Java 8的博客,但不再是每个星期五(有些人已经注意到)。

在Java 8 Friday系列的最后一篇简短文章中,我们要重申一个事实,我们相信未来属于功能性关系数据转换(与ORM相对) 。 我们使用面向对象的软件开发范例已经花费了大约20年的时间。 我们许多人对此非常教条。 然而,在过去的十年中,“新”范式已开始在编程社区中获得越来越多的关注: 函数式编程

但是,函数式编程并不是什么新鲜事物。 Lisp一直是非常早期的函数式编程语言。 XSLT和SQL也具有一定的功能(并且是声明性的!)。 由于我们是SQL功能(和声明性!)性质的忠实拥护者,我们为我们现在拥有Java中复杂的工具来转换从SQL数据库提取的表格数据而感到非常兴奋。 溪流!

SQL结果集与流非常相似

正如我们之前指出的那样, JDBC ResultSet和Java 8 Streams非常相似 。 当您使用jOOQ(使用org.jooq.Result替换JDBC ResultSet)时,情况org.jooq.Resultorg.jooq.Result扩展了java.util.List ,因此自动继承了所有Streams功能。 考虑以下查询,该查询允许获取BOOK和AUTHOR记录之间的一对多关系:

Map<Record2<String, String>, 
    List<Record2<Integer, String>>> booksByAuthor =

// This work is performed in the database
// --------------------------------------
ctx.select(
        BOOK.ID,
        BOOK.TITLE,
        AUTHOR.FIRST_NAME,
        AUTHOR.LAST_NAME
    )
   .from(BOOK)
   .join(AUTHOR)
   .on(BOOK.AUTHOR_ID.eq(AUTHOR.ID))
   .orderBy(BOOK.ID)
   .fetch()

// This work is performed in Java memory
// -------------------------------------
   .stream()

   // Group BOOKs by AUTHOR
   .collect(groupingBy(

        // This is the grouping key      
        r -> r.into(AUTHOR.FIRST_NAME, 
                    AUTHOR.LAST_NAME),

        // This is the target data structure
        LinkedHashMap::new,

        // This is the value to be produced for each
        // group: A list of BOOK
        mapping(
            r -> r.into(BOOK.ID, BOOK.TITLE),
            toList()
        )
    ));

对于习惯使用jOOQ编写SQL的人来说,Java 8 Streams API的流利性是非常习惯的。 显然,您还可以使用jOOQ以外的其他工具,例如Spring的JdbcTemplate或Apache Commons DbUtils,或仅将JDBC ResultSet包装在迭代器中……

与ORM相比,这种方法的优点是根本没有任何魔术发生。 每条映射逻辑都是明确的,而且由于使用Java泛型,因此完全是类型安全的。 在此示例中, booksByAuthor输出的类型很复杂,读/写有点困难,但它也具有充分的描述性和实用性。

与POJO相同的功能转换

如果您对使用jOOQ的Record2元组类型不太满意,那么没问题。 您可以这样指定自己的数据传输对象:

class Book {
    public int id;
    public String title;

    @Override
    public String toString() { ... }

    @Override
    public int hashCode() { ... }

    @Override
    public boolean equals(Object obj) { ... }
}

static class Author {
    public String firstName;
    public String lastName;

    @Override
    public String toString() { ... }

    @Override
    public int hashCode() { ... }

    @Override
    public boolean equals(Object obj) { ... }
}

使用上述DTO,您现在可以利用jOOQ的内置POJO映射将jOOQ记录转换为您自己的域类:

Map<Author, List<Book>> booksByAuthor =
ctx.select(
        BOOK.ID,
        BOOK.TITLE,
        AUTHOR.FIRST_NAME,
        AUTHOR.LAST_NAME
    )
   .from(BOOK)
   .join(AUTHOR)
   .on(BOOK.AUTHOR_ID.eq(AUTHOR.ID))
   .orderBy(BOOK.ID)
   .fetch()
   .stream()
   .collect(groupingBy(

        // This is the grouping key      
        r -> r.into(Author.class),
        LinkedHashMap::new,

        // This is the grouping value list
        mapping(
            r -> r.into(Book.class),
            toList()
        )
    ));

显性与隐性

在Data Geekery,我们相信Java开发人员的新时代已经开始。 一个时代,Annotatiomania™(最终!)结束了,人们不再通过注释魔术来承担所有隐性行为。 ORM依赖大量规范来解释每个注释如何与其他注释一起工作。 很难对JPA带给我们的这种不太了解的注释语言进行逆向工程(或调试!)。

在另一方面,SQL是很容易理解的。 表是一种易于处理的数据结构,如果您需要将这些表转换为更面向对象或更具层次结构的表,则可以简单地将函数应用于这些表并自己对值进行分组! 通过对这些值进行显式分组,您将完全控制映射,就像使用jOOQ一样,您将完全控制SQL。

这就是为什么我们认为,在未来5年中,ORM将失去相关性,人们将开始使用Java 8 Streams再次拥抱显式无状态 魔术的数据转换技术。

翻译自: https://www.javacodegeeks.com/2014/07/java-8-friday-more-functional-relational-transformation.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值