在Data Geekery ,我们喜欢Java。 而且,由于我们真的很喜欢jOOQ的流畅的API和查询DSL ,我们对Java 8将为我们的生态系统带来什么感到非常兴奋。

Java 8星期五

每个星期五,我们都会向您展示一些不错的教程风格的Java 8新功能,这些功能利用了lambda表达式,扩展方法和其他好东西。 您可以在GitHub上找到源代码 。

不再需要ORM

在过去的十年中,关于ORM(对象关系映射)的有用性的争论一直在进行。 尽管许多人会同意Hibernate和JPA很好地解决了许多问题(大多数情况是复杂对象图的持久性),但其他人可能会认为, 映射复杂性对于以数据为中心的应用程序来说大多数是过分的 。

JPA通过在接收目标类型上使用硬连线的注释建立标准化的声明性映射规则来解决映射问题。 我们声称,许多以数据为中心的问题不应仅受这些注释的狭窄范围的限制,而应以更加实用的方式解决。 Java 8和新的Streams API最终使我们能够以非常简洁的方式执行此操作!

让我们从一个简单的示例开始,在该示例中,我们使用H2的INFORMATION_SCHEMA收集所有表及其列。 我们将要生成一个Map<String, List<String>>类型的临时数据结构来包含此信息。 为了简化SQL交互,我们将使用jOOQ (与往常一样,此博客上的内容令人震惊)。 这是我们准备的方法:

public static void main(String[] args)
throws Exception {Class.forName("org.h2.Driver");try (Connection c = getConnection("jdbc:h2:~/sql-goodies-with-mapping", "sa", "")) {// This SQL statement produces all table// names and column names in the H2 schemaString sql ="select table_name, column_name " +"from information_schema.columns " +"order by " +"table_catalog, " +"table_schema, " +"table_name, " +"ordinal_position";// This is jOOQ's way of executing the above// statement. Result implements List, which// makes subsequent steps much easierResult<Record> result =DSL.using(c).fetch(sql)}
}

现在我们已经设置了该查询,让我们看看如何从jOOQ Result中生成Map<String, List<String>>

DSL.using(c).fetch(sql).stream().collect(groupingBy(r -> r.getValue("TABLE_NAME"),mapping(r -> r.getValue("COLUMN_NAME"),toList()))).forEach((table, columns) -> System.out.println(table + ": " + columns));

上面的示例产生以下输出:

FUNCTION_COLUMNS: [ALIAS_CATALOG, ALIAS_SCHEMA, ...]
CONSTANTS: [CONSTANT_CATALOG, CONSTANT_SCHEMA, ...]
SEQUENCES: [SEQUENCE_CATALOG, SEQUENCE_SCHEMA, ...]

它是如何工作的? 让我们逐步进行

DSL.using(c).fetch(sql)// Here, we transform a List into a Stream.stream()// We're collecting Stream elements into a new
// collection type.collect(// The Collector is a grouping operation, producing
// a MapgroupingBy(// The grouping operation's group key is defined by
// the jOOQ Record's TABLE_NAME valuer -> r.getValue("TABLE_NAME"),// The grouping operation's group value is generated
// by this mapping expression...mapping(// ... which is essentially mapping each grouped
// jOOQ Record to the Record's COLUMN_NAME valuer -> r.getValue("COLUMN_NAME"),// ... and then collecting all those values into a
// java.util.List. WhewtoList())))// Once we have this List<String, List<String>> we
// can simply consume it with the following Consumer
// lambda expression.forEach((table, columns) -> System.out.println(table + ": " + columns));

得到它了? 第一次玩这些东西时,肯定有些棘手。 起初,新类​​型,泛型泛型,lambda表达式的组合可能会有些混乱。 最好的办法就是简单地练习这些东西,直到您掌握了它。 毕竟,与以前的Java Collections API相比,整个Streams API确实是一场革命。

好消息是:此API是最终的,并将保留。 练习每一分钟都是对自己未来的投资。

请注意,以上程序使用了以下静态导入:

import static java.util.stream.Collectors.*;

还要注意,不再像数据库中那样对输出进行排序。 这是因为groupingBy收集器返回java.util.HashMap 。 在我们的例子中,我们可能更喜欢将东西收集到java.util.LinkedHashMap ,该对象保留插入/收集的顺序:

DSL.using(c).fetch(sql).stream().collect(groupingBy(r -> r.getValue("TABLE_NAME"),// Add this Supplier to the groupingBy// method callLinkedHashMap::new,mapping(r -> r.getValue("COLUMN_NAME"),toList()))).forEach(...);

我们可以继续使用其他转换结果的方法。 想象一下,我们想根据上述模式生成简单的DDL。 非常简单 首先,我们需要选择列的数据类型。 我们将其简单地添加到我们的SQL查询中:

String sql ="select " +"table_name, " +"column_name, " +"type_name " + // Add the column type"from information_schema.columns " +"order by " +"table_catalog, " +"table_schema, " +"table_name, " +"ordinal_position";

我还为示例引入了一个新的本地类,以包装名称和类型属性:

class Column {final String name;final String type;Column(String name, String type) {this.name = name;this.type = type;}
}

现在,让我们看看如何更改Streams API方法调用:

result.stream().collect(groupingBy(r -> r.getValue("TABLE_NAME"),LinkedHashMap::new,mapping(// We now collect this new wrapper type// instead of just the COLUMN_NAMEr -> new Column(r.getValue("COLUMN_NAME", String.class),r.getValue("TYPE_NAME", String.class)),toList()))).forEach((table, columns) -> {// Just emit a CREATE TABLE statementSystem.out.println("CREATE TABLE " + table + " (");// Map each "Column" type into a String// containing the column specification,// and join them using comma and// newline. Done!System.out.println(columns.stream().map(col -> "  " + col.name +" " + col.type).collect(Collectors.joining(",\n")));System.out.println(");");});

输出再好不过了!

CREATE TABLE CATALOGS(CATALOG_NAME VARCHAR
);
CREATE TABLE COLLATIONS(NAME VARCHAR,KEY VARCHAR
);
CREATE TABLE COLUMNS(TABLE_CATALOG VARCHAR,TABLE_SCHEMA VARCHAR,TABLE_NAME VARCHAR,COLUMN_NAME VARCHAR,ORDINAL_POSITION INTEGER,COLUMN_DEFAULT VARCHAR,IS_NULLABLE VARCHAR,DATA_TYPE INTEGER,CHARACTER_MAXIMUM_LENGTH INTEGER,CHARACTER_OCTET_LENGTH INTEGER,NUMERIC_PRECISION INTEGER,NUMERIC_PRECISION_RADIX INTEGER,NUMERIC_SCALE INTEGER,CHARACTER_SET_NAME VARCHAR,COLLATION_NAME VARCHAR,TYPE_NAME VARCHAR,NULLABLE INTEGER,IS_COMPUTED BOOLEAN,SELECTIVITY INTEGER,CHECK_CONSTRAINT VARCHAR,SEQUENCE_NAME VARCHAR,REMARKS VARCHAR,SOURCE_DATA_TYPE SMALLINT
);

ORM时代可能刚刚结束

这是一个强有力的声明。 ORM时代可能已经结束。 为什么? 因为使用函数表达式转换数据集是软件工程中最强大的概念之一。 函数式编程非常有表现力,也非常通用。 它是数据和数据流处理的核心。 我们的Java开发人员已经知道现有的功能语言。 例如,每个人以前都使用过SQL。 想一想。 使用SQL,您可以声明表源,将它们投影/转换为新的元组流,并将它们作为派生表提供给其他更高级的SQL语句或Java程序。

如果使用XML,则可以使用XSLT声明XML转换,并使用XProc pipelining将结果馈送到其他XML处理实体,例如另一个XSL样式表。

Java 8的Streams没什么。 使用SQL和Streams API是最强大的数据处理概念之一。 如果将jOOQ添加到堆栈,则可以从对数据库记录和查询API的类型安全访问中受益。 想象一下使用jOOQ的流畅API而不是使用SQL字符串编写上一条语句。

整个方法链可以是一个单一的流利数据转换链,如下所示:

DSL.using(c).select(COLUMNS.TABLE_NAME,COLUMNS.COLUMN_NAME,COLUMNS.TYPE_NAME).from(COLUMNS).orderBy(COLUMNS.TABLE_CATALOG,COLUMNS.TABLE_SCHEMA,COLUMNS.TABLE_NAME,COLUMNS.ORDINAL_POSITION).fetch()  // jOOQ ends here.stream() // Streams start here.collect(groupingBy(r -> r.getValue(COLUMNS.TABLE_NAME),LinkedHashMap::new,mapping(r -> new Column(r.getValue(COLUMNS.COLUMN_NAME),r.getValue(COLUMNS.TYPE_NAME)),toList()))).forEach((table, columns) -> {// Just emit a CREATE TABLE statementSystem.out.println("CREATE TABLE " + table + " (");// Map each "Column" type into a String// containing the column specification,// and join them using comma and// newline. Done!System.out.println(columns.stream().map(col -> "  " + col.name +" " + col.type).collect(Collectors.joining(",\n")));System.out.println(");");});

Java 8是未来,借助jOOQ,Java 8和Streams API,您可以编写功能强大的数据转换API。 希望我们让您像我们一样兴奋! 请继续关注此博客上更多精彩的Java 8内容。

翻译自: https://www.javacodegeeks.com/2014/04/java-8-friday-no-more-need-for-orms.html

Java 8 Friday:不再需要ORM相关推荐

  1. orm java_Java 8 Friday:不再需要ORM

    orm java 在Data Geekery ,我们喜欢Java. 而且,由于我们真的很喜欢jOOQ的流畅的API和查询DSL ,我们对Java 8将为我们的生态系统带来什么感到非常兴奋. Java ...

  2. 为什么Java 8中不再需要StringBuilder拼接字符串

    在Java开发者中,字符串的拼接占用资源高往往是热议的话题. 让我们深入讨论一下为什么会占用高资源. 在Java中,字符串对象是不可变的,意思是它一旦创建,你就无法再改变它.所以在我们拼接字符串的时候 ...

  3. java8 stringbuilder_为什么 Java 8 中不再需要 StringBuilder 拼接字符串

    在Java开发者中,字符串的拼接占用资源高往往是热议的话题. 让我们深入讨论一下为什么会占用高资源. 在Java中,字符串对象是不可变的,意思是它一旦创建,你就无法再改变它.所以在我们拼接字符串的时候 ...

  4. java异常总结---1.java.lang.ClassNotFoundException: org.springframework.orm.hibernate4.support.OpenSessio

    java异常总结---1.java.lang.ClassNotFoundException: org.springframework.orm.hibernate4.support.OpenSessio ...

  5. 【Java Web开发指南】ORM一些基础问题整理

    文章目录 1.什么是ORM?请说明两种常用的ORM框架的区别是什么. 2.在进行实体关系映射时,如果遇到实体类中的属性名与表中的字段名不一致的情况,该如何解决.请给出至少两种解决方案. 3.从线程安全 ...

  6. Java之手写实现ORM框架

    借鉴Mybatis框架手写一个ORM框架.mybatis整体架构中的整体思路是,首先解析一下配置文件,一个是框架的全局配置文件,一个是mapper配置文件,定义格式如下 <configurati ...

  7. Java对象关系映射(ORM)

    一.什么是对象关系映射 简单来说,对象关系映射即是将Java中的对象一一对应映射到MySQL(本文基于MySQL)的Table(表)中,通过对对象各个属性赋值来更新数据库. 官方的说,对象关系映射(O ...

  8. java小游戏之捕鱼达人,学了java,妈妈不再担心我去网吧游戏厅了!

    Java小项目捕鱼达人 跪求关注,祝关注我的人都:身体健康,财源广进,福如东海,寿比南山,早上贵子,从不掉发! 捕鱼达人这款游戏,相信和我年纪相仿的朋友,肯定很熟悉.在当时半智能手机和智能手机刚刚出现 ...

  9. Java 11已经不再完全免费,不要陷入Oracle的Java 11陷阱

    Java 11 已经发布.这是一个主要版本,因为它有长期支持(LTS).但甲骨文也将其设置为陷阱(故意或偶然). 陷阱 23年来,开发人员从Oracle下载了JDK并免费使用它.在您最喜爱的搜索引擎中 ...

最新文章

  1. 量子神经网络:人工智能研究的新范式
  2. XCTF-MISC-新手区-功夫再高也怕菜刀
  3. DMAR(DMA remapping)与 IOMMU
  4. 通过css样式,控制文字显示...
  5. 5.Struts2配置形式,覆盖
  6. 异常已存在具有相同键的条目。_从Viticis Fructus分离的环烯醚萜类化合物抑制紫杉醇诱导的小鼠机械性异常性疼痛...
  7. 基于Python3-Pygame的乒乓球游戏
  8. G - Super Jumping! Jumping! Jumping!(动态规划)
  9. Scratch互动编程手柄兼容mblock网易卡搭慧编程猫Mind+ 编程键盘手柄20210223
  10. word转换html分页,将网页(HTML)内容复制转贴到Word的分页控制
  11. 专访当当网张亮:深度解读分布式作业调度框架elastic-job
  12. 安工大计算机学院李雪,计算机学院本科生党支部召开党员大会
  13. 分享几款C/C++在线编译器
  14. Nginx编译时error: assignment makes pointer from integer without a cast处理
  15. 奢侈品典当价格以及流程又是如何的?现今哪些品牌的奢侈品押呗可以典当!
  16. 用工作流思想实现简单的校园请假系统
  17. 复制一个维基百科!—— 维基技术梳理
  18. Opensea到底是怎么交易NFT的
  19. 高龄白菜java学习第101天(java数据结构和算法(19))
  20. 两百行代码实现动态圣诞树—你值得拥有

热门文章

  1. String转Double
  2. 自定义SpringBoot的运行动画---美女
  3. matlab边算边出图命令,Matlab:不包含边境和工具栏的figure(移除保存图片的白边)...
  4. python定义函数prime判断是否是素数_用自定义函数判断素数 用C语言编写自定义函数prime(int x),判断x是否为素数?...
  5. python统计段落单词词频_使用Python统计文件中词频,并且生成词云
  6. Object.hashCode()与Object.equals()
  7. 转:RabbitMQ 消息队列特性知多少
  8. trackby_使用trackBy启动流程
  9. hibernate查询缓存_在Hibernate中启用实体和查询缓存
  10. 如何使用用户数据脚本在EC2实例上安装Apache Web Server