Timescale Code Quick Start Guides are designed to help you integrate Timescale into your own programs. They use your favorite programming language to explain how to connect to a Timescale database, create and manage hypertables, and ingest and query data.
This quick start guide walks you through:
- Connecting to TimescaleDB
- Creating a relational table
- Creating a hypertable
- Inserting data
- Executing a query
Before you start, make sure you have:
- Installed TimescaleDB. For more information, see the installation documentation.
- Installed the Java Development Kit (JDK).
- Installed the PostgreSQL JDBC driver.
All code in this quick start is for Java 16 and later. If you are working with older JDK versions, use legacy coding techniques.
In this section, you create a connection to TimescaleDB using an application in
a single file. You can use any of your favorite build tools, including gradle
or maven
.
Create a directory containing a text file called
Main.java
, with this content:package com.timescale.java;public class Main {public static void main(String... args) {System.out.println("Hello, World!");}}From the command line in the current directory, run the application:
java Main.javaIf the command is successful,
Hello, World!
line output is printed to your console.Import the PostgreSQL JDBC driver. If you are using a dependency manager, include the PostgreSQL JDBC Driver as a dependency.
Download the JAR artifact of the JDBC Driver and save it with the
Main.java
file.Import the
JDBC Driver
into the Java application and display a list of available drivers for the check:package com.timescale.java;import java.sql.DriverManager;public class Main {public static void main(String... args) {DriverManager.drivers().forEach(System.out::println);}}Run all the examples:
java -cp *.jar Main.java
If the command is successful, a string similar to
org.postgresql.Driver@7f77e91b
is printed to your console. This means that you
are ready to connect to TimescaleDB from Java.
Locate your TimescaleDB credentials and use them to compose a connection string for JDBC.
You'll need:
- password
- username
- host URL
- port
- database name
Compose your connection string variable, using this format:
var connUrl = "jdbc:postgresql://<HOSTNAME>:<PORT>/<DATABASE_NAME>?user=<USERNAME>&password=<PASSWORD>";For more information about creating connection strings, see the JDBC documentation.
Warning
This method of composing a connection string is for test or development purposes only. For production, use environment variables for sensitive details like your password, hostname, and port number.
package com.timescale.java;import java.sql.DriverManager;import java.sql.SQLException;public class Main {public static void main(String... args) throws SQLException {var connUrl = "jdbc:postgresql://<HOSTNAME>:<PORT>/<DATABASE_NAME>?user=<USERNAME>&password=<PASSWORD>";var conn = DriverManager.getConnection(connUrl);System.out.println(conn.getClientInfo());}}Run the code:
java -cp *.jar Main.javaIf the command is successful, a string similar to
{ApplicationName=PostgreSQL JDBC Driver}
is printed to your console.
In this section, you create a table called sensors
which holds the ID, type,
and location of your fictional sensors. Additionally, you create a hypertable
called sensor_data
which holds the measurements of those sensors. The
measurements contain the time, sensor_id, temperature reading, and CPU
percentage of the sensors.
Compose a string which contains the SQL statement to create a relational table. This example creates a table called
sensors
, with columnsid
,type
andlocation
:CREATE TABLE sensors (id SERIAL PRIMARY KEY,type TEXT NOT NULL,location TEXT NOT NULL);Create a statement, execute the query you created in the previous step, and check that the table was created successfully:
package com.timescale.java;import java.sql.DriverManager;import java.sql.SQLException;public class Main {public static void main(String... args) throws SQLException {var connUrl = "jdbc:postgresql://<HOSTNAME>:<PORT>/<DATABASE_NAME>?user=<USERNAME>&password=<PASSWORD>";var conn = DriverManager.getConnection(connUrl);var createSensorTableQuery = """CREATE TABLE sensors (id SERIAL PRIMARY KEY,type TEXT NOT NULL,location TEXT NOT NULL)""";try (var stmt = conn.createStatement()) {stmt.execute(createSensorTableQuery);}var showAllTablesQuery = "SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = 'public'";try (var stmt = conn.createStatement();var rs = stmt.executeQuery(showAllTablesQuery)) {System.out.println("Tables in the current database: ");while (rs.next()) {System.out.println(rs.getString("tablename"));}}}}
When you have created the relational table, you can create a hypertable. Creating tables and indexes, altering tables, inserting data, selecting data, and most other tasks are executed on the hypertable.
Create a
CREATE TABLE
SQL statement for your hypertable. Notice how the hypertable has the compulsory time column:CREATE TABLE sensor_data (time TIMESTAMPTZ NOT NULL,sensor_id INTEGER REFERENCES sensors (id),value DOUBLE PRECISION);Create a statement, execute the query you created in the previous step:
SELECT create_hypertable('sensor_data', by_range('time'));Note
The
by_range
andby_hash
dimension builder is an addition to TimescaleDB 2.13.Execute the two statements you created, and commit your changes to the database:
package com.timescale.java;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.util.List;public class Main {public static void main(String... args) {final var connUrl = "jdbc:postgresql://<HOSTNAME>:<PORT>/<DATABASE_NAME>?user=<USERNAME>&password=<PASSWORD>";try (var conn = DriverManager.getConnection(connUrl)) {createSchema(conn);insertData(conn);} catch (SQLException ex) {System.err.println(ex.getMessage());}}private static void createSchema(final Connection conn) throws SQLException {try (var stmt = conn.createStatement()) {stmt.execute("""CREATE TABLE sensors (id SERIAL PRIMARY KEY,type TEXT NOT NULL,location TEXT NOT NULL)""");}try (var stmt = conn.createStatement()) {stmt.execute("""CREATE TABLE sensor_data (time TIMESTAMPTZ NOT NULL,sensor_id INTEGER REFERENCES sensors (id),value DOUBLE PRECISION)""");}try (var stmt = conn.createStatement()) {stmt.execute("SELECT create_hypertable('sensor_data', by_range('time'))");}}}
You can insert data into your hypertables in several different ways. In this section, you can insert single rows, or insert by batches of rows.
Open a connection to the database, use prepared statements to formulate the
INSERT
SQL statement, then execute the statement:final List<Sensor> sensors = List.of(new Sensor("temperature", "bedroom"),new Sensor("temperature", "living room"),new Sensor("temperature", "outside"),new Sensor("humidity", "kitchen"),new Sensor("humidity", "outside"));for (final var sensor : sensors) {try (var stmt = conn.prepareStatement("INSERT INTO sensors (type, location) VALUES (?, ?)")) {stmt.setString(1, sensor.type());stmt.setString(2, sensor.location());stmt.executeUpdate();}}
If you want to insert a batch of rows by using a batching mechanism. In this
example, you generate some sample time-series data to insert into the
sensor_data
hypertable:
This section covers how to execute queries against your database.
Define the SQL query you'd like to run on the database. This example combines time-series and relational data. It returns the average values for every 15 minute interval for sensors with specific type and location.
SELECT time_bucket('15 minutes', time) AS bucket, avg(value)FROM sensor_dataJOIN sensors ON sensors.id = sensor_data.sensor_idWHERE sensors.type = ? AND sensors.location = ?GROUP BY bucketORDER BY bucket DESC;Execute the query with the prepared statement and read out the result set for all
a
-type sensors located on thefloor
:try (var stmt = conn.prepareStatement("""SELECT time_bucket('15 minutes', time) AS bucket, avg(value)FROM sensor_dataJOIN sensors ON sensors.id = sensor_data.sensor_idWHERE sensors.type = ? AND sensors.location = ?GROUP BY bucketORDER BY bucket DESC""")) {stmt.setString(1, "temperature");stmt.setString(2, "living room");try (var rs = stmt.executeQuery()) {while (rs.next()) {System.out.printf("%s: %f%n", rs.getTimestamp(1), rs.getDouble(2));}}}If the command is successful, you'll see output like this:
2021-05-12 23:30:00.0: 0,5086492021-05-12 23:15:00.0: 0,4778522021-05-12 23:00:00.0: 0,4622982021-05-12 22:45:00.0: 0,4570062021-05-12 22:30:00.0: 0,568744...
Now that you're able to connect, read, and write to a TimescaleDB instance from your Java application, and generate the scaffolding necessary to build a new application from an existing TimescaleDB instance, be sure to check out these advanced TimescaleDB tutorials:
This section contains complete code samples.
Keywords
Found an issue on this page?Report an issue or Edit this page in GitHub.