使用jOOQ和JavaFX将SQL数据转换为图表

最近,我们已经展示了Java 8和函数式编程将如何为使用jOOQ和Java 8 lambda和Streams进行SQL数据的函数数据转换为Java开发人员带来新的视角。 今天,我们将这一步骤更进一步,将数据转换为JavaFX XYChart.Series以根据数据生成美观的条形图。

设置数据库

我们将在PostgreSQL数据库中再次使用世界银行开放数据的一小部分。 我们正在使用的数据如下:

DROP SCHEMA IF EXISTS world;CREATE SCHEMA world;CREATE TABLE world.countries (code CHAR(2) NOT NULL,year INT NOT NULL,gdp_per_capita DECIMAL(10, 2) NOT NULL,govt_debt DECIMAL(10, 2) NOT NULL
);INSERT INTO world.countries
VALUES ('CA', 2009, 40764, 51.3),('CA', 2010, 47465, 51.4),('CA', 2011, 51791, 52.5),('CA', 2012, 52409, 53.5),('DE', 2009, 40270, 47.6),('DE', 2010, 40408, 55.5),('DE', 2011, 44355, 55.1),('DE', 2012, 42598, 56.9),('FR', 2009, 40488, 85.0),('FR', 2010, 39448, 89.2),('FR', 2011, 42578, 93.2),('FR', 2012, 39759,103.8),('GB', 2009, 35455,121.3),('GB', 2010, 36573, 85.2),('GB', 2011, 38927, 99.6),('GB', 2012, 38649,103.2),('IT', 2009, 35724,121.3),('IT', 2010, 34673,119.9),('IT', 2011, 36988,113.0),('IT', 2012, 33814,131.1),('JP', 2009, 39473,166.8),('JP', 2010, 43118,174.8),('JP', 2011, 46204,189.5),('JP', 2012, 46548,196.5),('RU', 2009,  8616,  8.7),('RU', 2010, 10710,  9.1),('RU', 2011, 13324,  9.3),('RU', 2012, 14091,  9.4),('US', 2009, 46999, 76.3),('US', 2010, 48358, 85.6),('US', 2011, 49855, 90.1),('US', 2012, 51755, 93.8);

( 另请参阅本文,了解针对上述数据的另一套很棒的SQL查询 )

我们现在要做的是在两个不同的条形图中绘制两组值:

  • 2009-2012年间每个国家的人均GDP
  • 每个国家的债务占其2009年至2012年间每年GDP的百分比

然后,这将创建8个系列,两个图表中的每个系列都有四个数据点。 除上述内容外,我们还希望按2009-2012年之间的平均预测值对系列进行排序,以便可以轻松比较系列-进而比较国家/地区。 显然,通过结果图在视觉上比在文本上更易于解释,因此请保持关注,直到文章结尾。

使用jOOQ和JavaFX收集数据

在普通SQL中,我们为计算上述数据系列而编写的查询如下所示:

select COUNTRIES.YEAR, COUNTRIES.CODE, COUNTRIES.GOVT_DEBT 
from COUNTRIES 
join (select COUNTRIES.CODE, avg(COUNTRIES.GOVT_DEBT) avg from COUNTRIES group by COUNTRIES.CODE
) c1 
on COUNTRIES.CODE = c1.CODE 
order by avg asc, COUNTRIES.CODE asc, COUNTRIES.YEAR asc

换句话说,我们只需要从COUNTRIES表中选择相关列,就可以自动加入每个国家/地区的平均预测值,以便可以按该平均值对结果进行排序。 可以使用窗口函数来编写相同的查询。 我们稍后再讲。

我们将编写以下代码来使用jOOQ和JavaFX创建这样的条形图:

CategoryAxis xAxis = new CategoryAxis();
NumberAxis yAxis = new NumberAxis();
xAxis.setLabel("Country");
yAxis.setLabel("% of GDP");BarChart<String, Number> bc = new BarChart<>(xAxis, yAxis);
bc.setTitle("Government Debt");
bc.getData().addAll(// SQL data transformation, executed in the DB// -------------------------------------------DSL.using(connection).select(COUNTRIES.YEAR,COUNTRIES.CODE,COUNTRIES.GOVT_DEBT).from(COUNTRIES).join(table(select(COUNTRIES.CODE, avg(COUNTRIES.GOVT_DEBT).as("avg")).from(COUNTRIES).groupBy(COUNTRIES.CODE)).as("c1")).on(COUNTRIES.CODE.eq(field(name("c1", COUNTRIES.CODE.getName()), String.class)))// order countries by their average // projected value.orderBy(field(name("avg")),COUNTRIES.CODE,COUNTRIES.YEAR)// The result produced by the above statement// looks like this:// +----+----+---------+// |year|code|govt_debt|// +----+----+---------+// |2009|RU  |     8.70|// |2010|RU  |     9.10|// |2011|RU  |     9.30|// |2012|RU  |     9.40|// |2009|CA  |    51.30|// +----+----+---------+// Java data transformation, executed in app memory// ------------------------------------------------// Group results by year, keeping sort // order in place.fetchGroups(COUNTRIES.YEAR)// The generic type of this is inferred...// Stream<Entry<Integer, Result<//     Record3<BigDecimal, String, Integer>>// >>.entrySet().stream()// Map entries into { Year -> Projected value }.map(entry -> new XYChart.Series<>(entry.getKey().toString(),observableArrayList(// Map records into a chart Dataentry.getValue().map(country -> new XYChart.Data<String, Number>(country.getValue(COUNTRIES.CODE),country.getValue(COUNTRIES.GOVT_DEBT)))))).collect(toList())
);

真正有趣的是,我们可以从数据库中获取数据,然后将其一次转换为JavaFX数据结构。 整个过程几乎是一个Java语句。

SQL和Java完全分开

正如我们之前在此博客上所写的那样, 将以上方法与LINQ或JPQL的DTO提取功能进行比较时 ,存在非常重要的区别。 即使我们在一个语句中表示整个转换,SQL查询还是与Java内存数据转换完全分开。

在表达对数据库的SQL查询时,我们希望尽可能精确,以便能够计算最佳执行计划。 只有实现了数据集之后,Java 8 Stream转换才会启动。

当我们将上面的SQL-92兼容查询更改为使用超棒的窗口函数的SQL-1999兼容查询时,这一点的重要性就变得很清楚。 上面的语句的jOOQ部分可以由以下查询代替:

DSL.using(connection).select(COUNTRIES.YEAR,COUNTRIES.CODE,COUNTRIES.GOVT_DEBT).from(COUNTRIES).orderBy(avg(COUNTRIES.GOVT_DEBT).over(partitionBy(COUNTRIES.CODE)),COUNTRIES.CODE,COUNTRIES.YEAR);

…或在SQL中:

selectCOUNTRIES.YEAR,COUNTRIES.CODE,COUNTRIES.GOVT_DEBT
fromCOUNTRIES
order byavg(COUNTRIES.GOVT_DEBT) over (partition by COUNTRIES.CODE),COUNTRIES.CODE,COUNTRIES.YEAR

如您所见,运行此类报告时,至关重要的是要控制实际的SQL语句。 这样,您根本不可能通过窗口函数通过嵌套选择将排序重构为效率更高的排序。 更不用说重构数十行Java排序逻辑了。

是的 难以超越窗口功能之美

如果我们添加一些其他的JavaFX样板文件以将图表放入窗格,场景和舞台中,我们将在下面获得这些漂亮的图表:

带有JavaFX和jOOQ的SQL

带有JavaFX和jOOQ的SQL

自己玩

您可以自己下载并运行上面的示例。 只需下载以下示例并运行mvn clean install : https : //github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-javafx-example

翻译自: https://www.javacodegeeks.com/2015/01/transform-your-sql-data-into-charts-using-jooq-and-javafx.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/361061.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

有一只猪400斤,桥承重200斤,怎么过桥?

条件:1 猪是活猪,任何方案都不 能切割猪。2 故事发生在猪王国&#xff0c;不要引 入人的因素。3 是过桥&#xff0c;不是过河&#xff0c;不要 说游泳过去。4 是过桥&#xff0c;不是过涧&#xff0c;不要 说飞过去。5 桥是承重200斤的桥&#xff0c;把桥 挪到平地上抑或过另一…

node.js学习笔记(1)

一&#xff0e; 安装以及环境配置 安装路径 http://nodejs.cn/download/ 多种环境选择 环境变量的配置 Step1 先检查环境变量中的系统变量里面的path,查看是否加入了node.js 例如我的node.js安装路径是C:\Program Files\nodejs 那么&#xff0c;这个path里面就应该加…

do语句转化为局部函数一例

do: (do ((x a (b x)) (y c (d y))) ((test x y) (z x y)) (f x y)) 局部函数&#xff1a; (labels ((rec (x y) (cond ((test x y) (z x y)) (t (f x y) (rec (b x) (d y)))))) …

主要版本发布后Java开发人员应使用的15种工具

新部署的生存工具包&#xff1a;适用于Java开发人员的工具&#xff0c;这些工具经常将代码部署到生产中&#xff01; Takipi会检测生产中的所有错误&#xff0c;并像发生错误时一样显示变量值 立即部署并获得免费的T恤 适用于新部署的终极生存套件 与在僵尸末日场景下玩弄&…

js dom node.children与node.childNodes区别

不同点&#xff1a;node.children不会取到节点下面的TextNode但是node.childNodes会取到 共同点&#xff1a;两者都是集合类数组&#xff0c;可以通过索引的方式取到值也可以用for循环遍历 更多专业前端知识&#xff0c;请上 【猿2048】www.mk2048.com

Java EE 7批处理和魔兽世界–第2部分

今天&#xff0c;我将把第二部分带到我以前关于Java EE 7批处理和《魔兽世界–第1部分》的帖子中。 在本文中&#xff0c;我们将了解如何从第1部分中获得的数据中汇总和提取指标。 概括 批处理目的是下载魔兽世界拍卖行的数据&#xff0c;处理拍卖并提取指标。 这些指标将建立…

js导航条 二级滑动 模仿块级作用域

for(var i 1;i<7;i){    //因为首级标题有6个&#xff0c;对每个首级标题添加mouseover和mouseout事件。    //这里用到块级作用域(function(k){document.getElementById("p_"k).addEventListener(mouseover,function(event){document.getElementById(p_…

js 中的console.log有什么作用

主要是方便你调式javascript用的。你可以看到你在页面中输出的内容。 相比alert他的优点是&#xff1a; 他能看到结构话的东西&#xff0c;如果是alert&#xff0c;淡出一个对象就是[object object],但是console能看到对象的内容。console不会打断你页面的操作&#xff0c;如…

太糟糕了,Java 8没有Iterable.stream()

这是最近比较有趣的Stack Overflow问题之一&#xff1a; 为什么Iterable不提供stream&#xff08;&#xff09;和parallelStream&#xff08;&#xff09;方法&#xff1f; 最初&#xff0c;直接将Iterable转换为Stream似乎很直观&#xff0c;因为在90&#xff05;的用例中&a…

struts+swfupload实现批量图片上传(上):swfupload

custom_settings : {progressTarget : "fsUploadProgress",cancelButtonId : "btnCancel",uploadButtonId : "btnUpload",myFileListTarget : "idFileList" },custom_settings调用方法 this.customSettings.cancelButtonId 缩略图js …

40行中的持久性KeyValue Server和一个可悲的事实

再次出现。. 回顾 Peters关于Unsafe用法的书面概述 &#xff0c;我将简要介绍一下Java中的低级技术如何通过启用更高级别的抽象或允许Java性能级别来节省开发工作可能很多人都不知道。 我的主要观点是表明&#xff0c;将对象转换为字节&#xff0c;反之亦然是一个重要的基础&a…

cookie 和session 的区别

session是保存在服务器端的&#xff0c;cookie是保存在客户端的。 二者的定义&#xff1a; 当你在浏览网站的时候&#xff0c;WEB 服务器会先送一小小资料放在你的计算机上&#xff0c;Cookie 会帮你在网站上所打的文字或是一些选择&#xff0c;都纪录下来。当下次你再光临同一…

javascript - dom

动态设置事件&#xff1a; 1. <input type"button" value"val1" οnclick"fn1();"/>; 2. ie支持 attachEventw3c标准 addEventListenerif (!window.event) {document.getElementById("btn").addEventListener("click…

ajax提交手机号去数据库验证并返回状态值

<script type"text/javascript">$(function(){$(.agree_regi).click(function(){var phone $.trim($("#phone").val());if(phone ""){NewAlert(2,"请输入手机号",null);return false;}else{var reg /^0?1[3|4|5|8|7][0-9]\d…

在同一台机器上启动多个JBoss A-MQ JVM

因此&#xff0c;我最近没有写过博客-只是很忙。 但是&#xff0c;我新年的决心是写一些博客&#xff0c;分享一些我经常遇到的事情&#xff0c;即使这些简单的事情可能会帮助一些人。 因此&#xff0c;对于本条目&#xff0c;我将展示一种在单台机器上启动多个JBoss A-MQ实例…

TreeMap源码分析——深入分析(基于JDK1.6)

TreeMap有Values、EntrySet、KeySet、PrivateEntryIterator、EntryIterator、ValueIterator、KeyIterator、DescendingKeyIterator、NavigableSubMap、AscendingSubMap、DescendingSubMap、SubMap、Entry共十三个内部类。Entry是在TreeMap中用于表示树的节点的内部类&#xff0…

使用Curator和ZooKeeper发现Hazelcast成员

在一个项目中&#xff0c;我正在私有云中设置Hazelcast集群。 在群集内&#xff0c;所有节点都必须互相看见&#xff0c;因此在引导过程中&#xff0c;Hazelcast将尝试查找其他群集成员。 没有服务器&#xff0c;并且所有节点都相等。 在Hazelcast中实现了多种发现成员的技术。…

Work Queue based multi-threading

http://www.codeproject.com/Articles/8886/Work-Queue-based-multi-threading转载于:https://www.cnblogs.com/hongjiumu/archive/2013/01/06/2846946.html

功能介面

目录 1.简介 2.理由 3. Lambda表达式 4.谓词<T> 5. BiPredicate <T&#xff0c;U> 6.函数<T&#xff0c;R> 7. BiFunction <T&#xff0c;U&#xff0c;R> 8.消费者<T> 9. BiConsumer <T&#xff0c;U> 10.供应商<T> 11.一元运算符&…

WMI 使用教程_.NET 入门教程

WMI 使用教程_.NET 入门教程 先介绍一下WMI 相关知识: 什么是WMI 呢&#xff1f; Windows 管理规范 (Windows Management Instrumentation ),它的主要功 能包括:访问本地主机的一些信息和服务,可以远程管理计算机(当然你必须拥有足够的权限) 也就是说可以象重起,关机,关闭进程,…