Persistence top

Get started with Spring Data JPA through the reference Learn Spring Data JPA course:

>> CHECK OUT THE COURSE

1. Introduction

In this article, we'll examine how we can store null values in our database using plain JDBC. We'll start by describing the reasons for using null values, followed by several code examples.

2. Using null Values

null is a keyword that transcends all programming languages. It represents a special value. It's a common perception that null has no value or that it represents nothing. Having a null stored in a database column means that space is reserved on the hard disk. If an appropriate value becomes available, we can store it in that space.

Another perception is that null is equal to zero or a blank string. Zero or a blank string in a specific context can have meaning, for example, zero items in the warehouse. Also, we can execute operations like sum or concat on these two values. But those operations have no meaning when dealing with null.

Using null values to represent special cases in our data has many advantages. One of those advantages is that most database engines exclude null values from internal functions such as sum or avg. On the other hand, when null is in our code, we can program special actions to mitigate the missing values.

Bringing null to the table also brings a couple of disadvantages. When writing code that deals with data containing null values, we have to handle that data differently. This can lead to bad-looking code, clutter, and bugs. Also, null values can have a variable length in the database. null stored in Integer and Byte columns will have different lengths.

3. Implementation

For our example, we'll use a simple Maven module with an H2 in-memory database. No other dependencies are required.

First, let's create our POJO class named Person. This class will have four fields. Id used as the primary key for our database, name, and lastName, which are strings and age represented as Integer. Age is not a required field and can be null:

public class Person {
    private Integer id;
    private String name;
    private String lastName;
    private Integer age;
    //getters and setters
}

To create a database table that reflects this Java class, we'll use the following SQL query:

CREATE TABLE Person (id INTEGER not null, name VARCHAR(50), lastName VARCHAR(50), age INTEGER, PRIMARY KEY (id));

With all that out of the way, now we can focus on our main goal. To set a null value into the Integer column, there are two defined ways in the PreparedStatement interface.

3.1. Using the setNull Method

With the setNull method, we're always sure that our field value is null before executing the SQL query. This allows us for more flexibility in the code.

With the column index, we must also supply the PreparedStatement instance with information about the underlying column type. In our case, this is java.sql.Types.INTEGER.

This method is reserved only for null values. For any other, we must use the appropriate method of PreparedStatement instance:

@Test
public void givenNewPerson_whenSetNullIsUsed_thenNewRecordIsCreated() throws SQLException {
    Person person = new Person(1, "John", "Doe", null);

    try (PreparedStatement preparedStatement = DBConfig.getConnection().prepareStatement(SQL)) {
        preparedStatement.setInt(1, person.getId());
        preparedStatement.setString(2, person.getName());
        preparedStatement.setString(3, person.getLastName());
        if (person.getAge() == null) {
            preparedStatement.setNull(4, Types.INTEGER);
        }
        else {
            preparedStatement.setInt(4, person.getAge());
        }
        int noOfRows = preparedStatement.executeUpdate();

        assertThat(noOfRows, equalTo(1));
    }
}

In the case that we don't check whether or not the getAge method returns null and calls the setInt method with a null value, we'll get a NullPointerException.

3.2. Using the setObject Method

The setObject method gives us less flexibility to deal with missing data in our code. We can pass the data we have, and the underlying structure will map Java Object types to SQL types.

Note that not all databases will allow passing null without specifying a SQL type. For example, the JDBC driver cannot infer SQL types from null.

To be on the safe side with this method, it's best to pass a SQL type to the setObject method:

@Test
public void givenNewPerson_whenSetObjectIsUsed_thenNewRecordIsCreated() throws SQLException {
    Person person = new Person(2, "John", "Doe", null);

    try (PreparedStatement preparedStatement = DBConfig.getConnection().prepareStatement(SQL)) {
        preparedStatement.setInt(1, person.getId());
        preparedStatement.setString(2, person.getName());
        preparedStatement.setString(3, person.getLastName());
        preparedStatement.setObject(4, person.getAge(), Types.INTEGER);
        int noOfRows = preparedStatement.executeUpdate();

        assertThat(noOfRows, equalTo(1));
    }
}

4. Conclusion

In this tutorial, we explained some basic usages of null values in databases. Then we provided examples of how to store null values inside Integer columns with plain JDBC.

As always, all code can be found over on GitHub.

Persistence bottom
Get started with Spring Data JPA through the reference Learn Spring Data JPA course: >> CHECK OUT THE COURSE
Persistence footer banner
Comments are closed on this article!