使用jOOQ和JavaFX将SQL数据转换为图表
最近,我們已經(jīng)展示了Java 8和函數(shù)式編程將如何為使用jOOQ和Java 8 lambda和Streams進行SQL數(shù)據(jù)的函數(shù)數(shù)據(jù)轉換為Java開發(fā)人員帶來新的視角。 今天,我們將這一步驟更進一步,將數(shù)據(jù)轉換為JavaFX XYChart.Series以根據(jù)數(shù)據(jù)生成美觀的條形圖。
設置數(shù)據(jù)庫
 我們將在PostgreSQL數(shù)據(jù)庫中再次使用世界銀行開放數(shù)據(jù)的一小部分。 我們正在使用的數(shù)據(jù)如下: 
( 另請參閱本文,了解針對上述數(shù)據(jù)的另一套很棒的SQL查詢 )
我們現(xiàn)在要做的是在兩個不同的條形圖中繪制兩組值:
- 2009-2012年間每個國家的人均GDP
- 每個國家的債務占其2009年至2012年間每年GDP的百分比
然后,這將創(chuàng)建8個系列,兩個圖表中的每個系列都有四個數(shù)據(jù)點。 除上述內容外,我們還希望按2009-2012年之間的平均預測值對系列進行排序,以便可以輕松比較系列-進而比較國家/地區(qū)。 顯然,通過結果圖在視覺上比在文本上更易于解釋,因此請保持關注,直到文章結尾。
使用jOOQ和JavaFX收集數(shù)據(jù)
在普通SQL中,我們?yōu)橛嬎闵鲜鰯?shù)據(jù)系列而編寫的查詢如下所示:
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表中選擇相關列,就可以自動加入每個國家/地區(qū)的平均預測值,以便可以按該平均值對結果進行排序。 可以使用窗口函數(shù)來編寫相同的查詢。 我們稍后再講。
我們將編寫以下代碼來使用jOOQ和JavaFX創(chuàng)建這樣的條形圖:
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()) );真正有趣的是,我們可以從數(shù)據(jù)庫中獲取數(shù)據(jù),然后將其一次轉換為JavaFX數(shù)據(jù)結構。 整個過程幾乎是一個Java語句。
SQL和Java完全分開
正如我們之前在此博客上所寫的那樣, 將以上方法與LINQ或JPQL的DTO提取功能進行比較時 ,存在非常重要的區(qū)別。 即使我們在一個語句中表示整個轉換,SQL查詢還是與Java內存數(shù)據(jù)轉換完全分開。
在表達對數(shù)據(jù)庫的SQL查詢時,我們希望盡可能精確,以便能夠計算最佳執(zhí)行計劃。 只有實現(xiàn)了數(shù)據(jù)集之后,Java 8 Stream轉換才會啟動。
當我們將上面的SQL-92兼容查詢更改為使用超棒的窗口函數(shù)的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語句。 這樣,您根本不可能通過窗口函數(shù)通過嵌套選擇將排序重構為效率更高的排序。 更不用說重構數(shù)十行Java排序邏輯了。
是的 難以超越窗口功能之美
如果我們添加一些其他的JavaFX樣板文件以將圖表放入窗格,場景和舞臺中,我們將在下面獲得這些漂亮的圖表:
帶有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
總結
以上是生活随笔為你收集整理的使用jOOQ和JavaFX将SQL数据转换为图表的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 四折页标准尺寸 四折页标准尺寸是什么
- 下一篇: 公斤单位是什么字母 公斤单位怎么表示
