How do I insert a record into Microsoft Access database and get the generated key?

In this tutorial, we’ll guide you through the process of inserting records into an MS Access Database. In the code snippet below we are using the UCanAccess JDBC driver, you can find the Maven dependencies at the end of this tutorial.

Setting Up The Connection

Firstly, we need to set up a connection to our MS Access database. This is done by specifying the path of your database file (.mdb or .accdb) in the JDBC URL and then getting a connection from DriverManager.

String url = "jdbc:ucanaccess://C:/Users/wayan/Temp/musicdb.accdb";
try (Connection connection = DriverManager.getConnection(url)) {
    ...
} catch (SQLException e) {
    e.printStackTrace();
}

Preparing the SQL Statement

Next step is to prepare our SQL insert statement. We use a PreparedStatement – it handles the tedious task of substituting the respective parameters into the placeholders ("?") in our SQL statement.

String sql = "insert into album (title, release_date, created) values (?, ?, ?)";

PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);

Setting Parameters and Executing the SQL Statement

After defining our SQL statement with placeholders, we replace these placeholders with actual values using the setter methods (setInt(), setString(), setDate(), etc.) provided by the PreparedStatement class. Once, the placeholders have been replaced with actual values, we call executeUpdate() method on the PreparedStatement object to execute the SQL statement.

ps.setString(1, "With the Beatles");
ps.setDate(2, Date.valueOf(LocalDate.of(1963, Month.NOVEMBER, 22)));
ps.setTimestamp(3, Timestamp.valueOf(LocalDateTime.now()));
int rowCount = ps.executeUpdate();
System.out.println("rowCount = " + rowCount);

In the code snippet above we set all placeholders with values we want to insert into the database, and then the statement is executed. The new record gets added to the database. We also keep the rowCount returned by the executeUpdate() method.

Get the Generated Key Value

When creating the PreparedStatement object we also passes the Statement.RETURN_GENERATED_KEYS parameter, this will allow us to get the generated key from the statement object after executing the query.

ResultSet generatedKeys = ps.getGeneratedKeys();
long generatedKey = 1L;
while (generatedKeys.next()) {
    generatedKey = generatedKeys.getLong(1);
}
System.out.println("Generated Key = " + generatedKey);

The Entire Code Snippet

Here is the entire Java class.

package org.kodejava.jdbc;

import java.sql.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;

public class MSAccessInsert {
    public static void main(String[] args) {
        String url = "jdbc:ucanaccess://C:/Users/wayan/Temp/musicdb.accdb";
        try (Connection connection = DriverManager.getConnection(url)) {
            String sql = "insert into album (title, release_date, created) values (?, ?, ?)";

            PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            ps.setString(1, "With the Beatles");
            ps.setDate(2, Date.valueOf(LocalDate.of(1963, Month.NOVEMBER, 22)));
            ps.setTimestamp(3, Timestamp.valueOf(LocalDateTime.now()));

            int rowCount = ps.executeUpdate();
            System.out.println("rowCount = " + rowCount);

            ResultSet generatedKeys = ps.getGeneratedKeys();
            long generatedKey = 1L;
            while (generatedKeys.next()) {
                generatedKey = generatedKeys.getLong(1);
            }
            System.out.println("Generated Key = " + generatedKey);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

The code above inserts a new record into the album table in the Access database. Remember to handle any SQLException that may be thrown while interacting with the database.

And that’s it! You have successfully inserted a record into an MS Access database using UCanAccess in Java. Whether you’re creating a small application or dealing with large-scale data management, UCanAccess is an easy, efficient way to work with MS Access databases in Java applications.

Maven Dependencies

<dependency>
    <groupId>io.github.spannm</groupId>
    <artifactId>ucanaccess</artifactId>
    <version>5.1.1</version>
</dependency>

Maven Central

How do I select a record from Microsoft Access Database?

UCanAccess is a pure Java JDBC Driver implementation which allows Java developers and JDBC client programs to read and write Microsoft Access database files (.mdb and .accdb).

In this tutorial, we will demonstrate how to configure a project with UCanAccess and create a simple Java application to select data from an MS Access database.

Establishing a Connection

Before you can interact with a database, you need to establish a connection to it. The following is an example of how to establish a connection using UCanAccess:

String url = "jdbc:ucanaccess://C:/Users/wayan/Temp/musicdb.accdb;";
try (Connection connection = DriverManager.getConnection(url)) {
    System.out.println("connection = " + connection);
    // Rest of the code goes here...
} catch (SQLException e) {
    e.printStackTrace();
}

In the code above, we create a connection URL using the absolute path to our Access database file. Then, we obtain a connection object by calling DriverManager.getConnection(url).

Fetching Data from the Database

Once the connection is established, we can execute SQL queries against the database. Here, let’s create a query to select some data:

String query = "select id, title, release_date from album where id = ?";

PreparedStatement ps = connection.prepareStatement(query);
ps.setLong(1, 1L);

ResultSet rs = ps.executeQuery();
while (rs.next()) {
    System.out.printf("id=%s, title=%s, released_date=%s%n",
            rs.getLong("id"), rs.getString("title"),
            rs.getDate("release_date"));
}

In this code, we create a PreparedStatement object, which enables us to execute parameterized SQL queries in a secure and efficient manner. Here, our SQL query includes a parameter, represented by the ? symbol, which we then set using setLong(). This would replace the ? with the value 1L.

We then execute our query by calling executeQuery() on the PreparedStatement object which returns a ResultSet object. This object represents the result set of the query.

We then loop through the result set and print each record using rs.next(), which is used to iterate through the ResultSet.

Full Code

package org.kodejava.jdbc;

import java.sql.*;

public class MSAccessSelect {
    public static void main(String[] args) {
        String url = "jdbc:ucanaccess://C:/Users/wayan/Temp/musicdb.accdb;";
        try (Connection connection = DriverManager.getConnection(url)) {
            System.out.println("connection = " + connection);

            String query = "select id, title, release_date from album where id = ?";

            PreparedStatement ps = connection.prepareStatement(query);
            ps.setLong(1, 1L);

            ResultSet rs = ps.executeQuery();
            while (rs.next()) {
                System.out.printf("id=%s, title=%s, released_date=%s%n",
                        rs.getLong("id"), rs.getString("title"),
                        rs.getDate("release_date"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Remember to handle SQL exceptions that might be thrown during the interaction with the database. And there you have it! Now you know how to work with MS Access Database using UCanAccess in Java. Happy coding!

Maven Dependencies

<dependency>
    <groupId>io.github.spannm</groupId>
    <artifactId>ucanaccess</artifactId>
    <version>5.1.1</version>
</dependency>

Maven Central

How do I get the auto-generated key in JdbcTemplate?

Spring JDBC simplifies database operations by providing an abstraction layer over traditional JDBC. In this blog post, we’ll walk through a practical example of using Spring JDBC to insert a record into a database and obtain the generated key for the newly inserted record.

First, let’s look at the complete code snippet:

package org.kodejava.spring.jdbc;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;

import java.math.BigInteger;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;

public class InsertDemoObtainsKey {
    public static void main(String[] args) {
        String insert = "INSERT INTO record (title, release_date, artist_id, label_id, created) VALUES (?, ?, ?, ?, ?)";

        JdbcTemplate template = new JdbcTemplate(new DriverManagerDataSource("jdbc:mysql://localhost/musicdb", "root", ""));
        KeyHolder keyHolder = new GeneratedKeyHolder();

        template.update(con -> {
            PreparedStatement ps = con.prepareStatement(insert, PreparedStatement.RETURN_GENERATED_KEYS);
            ps.setString(1, "Let It Be");
            ps.setDate(2, Date.valueOf(LocalDate.of(1970, Month.MAY, 8)));
            ps.setLong(3, 1L);
            ps.setLong(4, 1L);
            ps.setTimestamp(5, Timestamp.valueOf(LocalDateTime.now()));
            return ps;
        }, keyHolder);

        BigInteger key = (BigInteger) keyHolder.getKeys();
        System.out.println("key = " + key);
    }
}

This code demonstrates how to insert a record into a database table and retrieve the generated key using Spring’s JdbcTemplate.

DataSource Configuration

JdbcTemplate template = new JdbcTemplate(new DriverManagerDataSource("jdbc:mysql://localhost/musicdb", "root", ""));

Here, we create a JdbcTemplate instance, providing it with a DriverManagerDataSource. This data source points to our MySQL database named musicdb, with the username root and an empty password.

SQL Insert Statement

String insert = "INSERT INTO record (title, release_date, artist_id, label_id, created) VALUES (?, ?, ?, ?, ?)";

We define our SQL insert statement with placeholders for the values to be inserted. The table record is assumed to have columns title, release_date, artist_id, label_id, and created.

KeyHolder Initialization

KeyHolder keyHolder = new GeneratedKeyHolder();

A KeyHolder is used to hold the generated keys. In this case, we’re using a GeneratedKeyHolder.

Executing the Update

template.update(con -> {
PreparedStatement ps = con.prepareStatement(insert, PreparedStatement.RETURN_GENERATED_KEYS);
    ps.setString(1, "Let It Be");
    ps.setDate(2, Date.valueOf(LocalDate.of(1970, Month.MAY, 8)));
    ps.setLong(3, 1L);
    ps.setLong(4, 1L);
    ps.setTimestamp(5, Timestamp.valueOf(LocalDateTime.now()));
    return ps;
}, keyHolder);

We use the JdbcTemplate‘s update method, which takes two parameters: a PreparedStatementCreator and a KeyHolder. The PreparedStatementCreator is implemented using a lambda expression that sets the values for the placeholders in our SQL insert statement.

Retrieving the Generated Key

BigInteger key = (BigInteger) keyHolder.getKeys();
System.out.println("key = " + key);

After the update operation, we retrieve the generated key from the KeyHolder. The key is then printed to the console.

Summary

Using Spring JDBC simplifies the process of interacting with the database. In this example, we demonstrated how to insert a record into a MySQL database and retrieve the generated key using JdbcTemplate. This approach ensures clean and manageable code while leveraging the power of Spring’s abstraction over traditional JDBC.

Feel free to experiment with this code, adjusting the database connection details and SQL statements to fit your requirements. Happy coding!

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>6.1.10</version>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>8.4.0</version>
    </dependency>
</dependencies>

Maven Central Maven Central

How to recursively rename files with a specific suffix in Java?

The following code snippet show you how to recursively rename files with a specific suffix. In this example we are renaming a collection of resource bundles files which ends with _in.properties into _id.properties. The code snippet also count the number of files affected by the process. We use the Files.move() method to rename the file, if you want to copy the files instead of renaming them, then you can use the Files.copy() method.

Here is the complete code snippet:

package org.kodejava.io;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;

public class RenameResourceBundles {
    public static void main(String[] args) {
        String startDirectory = "C:/Projects/Hello";
        AtomicInteger counter = new AtomicInteger(0);

        try (Stream<Path> paths = Files.walk(Paths.get(startDirectory))) {
            paths.filter(Files::isRegularFile)
                    .filter(path -> path.toString().endsWith("_in.properties"))
                    .forEach(path -> renameFile(path, counter));
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("Total files renamed: " + counter.get());
    }

    private static void renameFile(Path path, AtomicInteger counter) {
        try {
            String newName = path.toString().replace("_in.properties", "_id.properties");
            Path newPath = Paths.get(newName);
            Files.move(path, newPath);
            System.out.println("Renamed: " + path + " to " + newPath);
            counter.incrementAndGet();
        } catch (IOException e) {
            System.out.println("Failed to rename: " + path);
            e.printStackTrace();
        }
    }
}

This code will recursively search through all subdirectories starting from the specified root directory and rename any files that end with _in.properties to _id.properties. The process prints the renamed file, and finally outputs the total number of files that were successfully renamed after traversing the directory tree.

The explanation of the code snippet above:

  • The Files.walk method is used to traverse the directory tree starting from the given directory.
  • The filter method is used to select only regular files that end with _in.properties.
  • The renameFile method handles the renaming of each file, replacing _in.properties with _id.properties.
  • An AtomicInteger named counter keeps track of the number of files renamed. AtomicInteger is used to handle the count in a thread-safe manner, which is useful if the code is ever modified to use parallel streams or multi-threading.
  • Inside the renameFile method, counter.incrementAndGet() is called each time a file is successfully renamed. This increments the counter by one.
  • After the Files.walk operation, the total number of renamed files is printed using System.out.println("Total files renamed: " + counter.get());.

How to copy files ending with a specific string to another file in Linux/macOS?

In Java 17, the Locale for Indonesia changed from in_ID to id_ID. In my project, the resource bundle files are named with the suffix _in.properties which is unrecognized by Java 17. To resolve this issue, I need to create copies of these resource bundle files that ends with _id.properties.

Here are solutions for both Linux/macOS (using Bash).

#!/bin/bash

# Set the root directory for the search
ROOT_DIR="/path/to/root_directory"

# Find all files ending with '_in.properties' and process each one
find "$ROOT_DIR" -type f -name "*_in.properties" | while read -r FILE; do
    # Construct file name by replacing '_in.properties' with '_id.properties'
    NEW_FILE="${FILE%_in.properties}_id.properties"
    # Copy the original file to the new file
    cp "$FILE" "$NEW_FILE"
done

Save this script as copy_properties.sh, make it executable with chmod +x copy_properties.sh, and run it with ./copy_properties.sh.

Explanation

  • find "$ROOT_DIR" -type f -name "*_in.properties": Finds all files ending with _in.properties.
  • while read -r FILE; do ... done: Loops through each found file.
  • ${FILE%_in.properties}_id.properties: Constructs the new file name by replacing _in.properties with _id.properties.
  • cp "$FILE" "$NEW_FILE": Copies the original file to the new file.

These scripts will recursively search the specified directory for files ending with _in.properties, then create a copy of each file with _id.properties in the same directory.