最近,我一直在研究 Groovy 如何简化 Java 的轻微笨拙之处。本文探讨了在 Java 和 Groovy 中使用 JDBC 连接到 PostgreSQL 数据库的一些差异。
安装 Java 和 Groovy
Groovy 基于 Java,需要安装 Java。您的 Linux 发行版的存储库中可能包含最新/不错的 Java 和 Groovy 版本,或者您可以按照这些说明安装 Groovy。对于 Linux 用户来说,SDKMan 是一个不错的替代方案,它提供了多个版本的 Java、Groovy 和许多其他相关工具。在本文中,我使用的是 SDK 发布的版本:
- Java 版本 11.0.12-open,OpenJDK 11
- Groovy 版本 3.0.8
回到问题
如果您尚未阅读,请查看这篇文章,了解如何安装 JDBC,以及这篇文章,了解如何设置 PostgreSQL。
无论您使用 Java 还是 Groovy,任何使用 JDBC 从数据库中提取数据的程序都会执行几个基本步骤:
- 建立与数据所在的数据库后端的
Connection
实例的连接。 - 使用 SQL 字符串,获取一个
Statement
实例(或类似的东西,如PreparedStatement
),它将处理 SQL 字符串的执行。 - 处理
ResultSet
实例,该实例是通过让Statement
实例执行查询返回的,例如,在控制台上打印返回的行。 - 完成后,关闭
Statement
和Connection
实例。
在 Java 中,代码和上面的列表之间的对应关系基本上是一对一的。Groovy 像往常一样,简化了流程。
Java 示例
这是 Java 代码,用于查看我在上面链接的第二篇文章中加载的土地覆盖数据
1 import java.sql.Connection;
2 import java.sql.Statement;
3 import java.sql.ResultSet;
4 import java.sql.DriverManager;
5 import java.sql.SQLException;
6 public class TestQuery {
7 public static void main(String[] args) {
8 final String url = "jdbc:postgresql://localhost/landcover";
9 final String user = "clh";
10 final String password = "carl-man";
11 try (Connection connection = DriverManager.getConnection(url, user, password)) {
12 try (Statement statement = connection.createStatement()) {
13 ResultSet res = statement.executeQuery("select distinct country_code from land_cover");
14 while (res.next()) {
15 System.out.println("country code " + res.getString("country_code"));
16 }
17 } catch (SQLException se) {
18 System.err.println(se.getMessage());
19 }
20 } catch (SQLException ce) {
21 System.err.println(ce.getMessage());
22 }
23 }
24 }
第 1-5 行是 JDBC 类必需的 import 语句。当然,我可以将其缩短为 import java.sql.*
,但现在这种做法有点不受欢迎。
第 6-24 行定义了公共类 TestQuery
,我将使用它来连接到数据库并打印主表的一些内容。
第 7-23 行定义了执行工作的 main
方法。
第 8-10 行定义了连接到数据库所需的三个字符串:URL、用户名和用户密码。
第 11-22 行使用 try-with-resources 打开 Connection
实例,并在完成后自动关闭它。
第 12-19 行使用另一个 try-with-resources 打开 Statement
实例,并在完成后自动关闭它。
第 13 行创建 ResultSet
实例来处理 SQL 查询,该查询使用 SELECT DISTINCT 从数据库的 land_cover 表中获取 country_code 的所有唯一值。
第 14-16 行处理查询返回的结果集,每行打印一个国家代码。
第 17-19 行和 20-22 行处理任何 SQL 异常。
Groovy 示例
我将在 Groovy 中做类似的事情
1 import groovy.sql.Sql
2 final String url = "jdbc:postgresql://localhost/landcover"
3 final String user = "me"
4 final String password = "my-password"
5 final String driver = "org.postgresql.Driver"
6 Sql.withInstance(url, user, password, driver) { sql ->
7 sql.eachRow('select distinct country_code from land_cover') { row ->
8 println "row.country_code ${row.country_code}"
9 }
10 }
好的,这要短得多——10 行而不是 24 行!以下是详细信息:
第 1 行是唯一需要的 import 语句。在我看来,不必为了三个不同的类而跳转查阅 JavaDocs 是一个明显的优势。
第 2-5 行定义了使用 Sql
类连接到数据库所需的四个字符串。前三个与 java.sql.Connection
相同;第四个命名了我想要的驱动程序。
第 6 行做了很多繁重的工作。方法调用是 Sql.withInstance()
,类似于 Groovy 中“with”的其他用法。这个调用:
- 创建一个
Sql
实例(连接、语句等)。 - 将闭包作为其最终参数,并将它创建的
Sql
实例传递给它。 - 在闭包退出时关闭
Sql
实例。
第 7 行调用 Sql
实例的 eachRow()
方法,包装结果集的创建和处理。eachRow()
方法将闭包作为其最终参数,并在处理从表中返回的数据行时将每个 row
传递给闭包。
Groovy 可以简化您的生活
对于那些日常工作涉及脚本编写和关系数据库的人来说,我认为从上面可以清楚地看出 Groovy 可以简化您的生活。以下是一些结束语:
- 我可以采用类似于 Java 版本的方式来完成此操作;例如,我可以调用
sql.query()
而不是调用sql.eachRow()
,后者将闭包作为其最后一个参数,并将结果集传递给该闭包,此时我可能会像在 Java 版本中使用while()
一样(或者可能是each()
)。 - 我还可以使用对
sql.rows()
的调用,一次性将结果行读入列表,这可以以类似于在列表上使用.collect()
的方式转换数据。 - 请记住,传递到
eachRow()
(或query()
)方法中的 SQL 可以是任意复杂的,包括表连接、分组、排序以及问题数据库支持的任何其他操作。 - 请注意,当使用
PreparedStatement
实例时,SQL 也可以参数化,如果 SQL 的任何部分来自编码人员的控制范围之外,这是一种避免 SQL 注入的好方法。 - 现在是时候引导勤奋的读者阅读 groovy.sql.Sql 的 JavaDocs。
Groovy 资源
Apache Groovy 语言站点提供了使用数据库的良好教程级概述,包括其他连接方式,以及其他操作,包括插入、删除、事务、批处理、分页——列表还在继续。该文档非常简洁易懂,至少部分原因是它所记录的设施本身就被设计成简洁易用!
评论已关闭。