Pages

Footer Pages

Spring Boot

Java String API

Java Conversions

Kotlin Programs

Kotlin Conversions

Java Threads Tutorial

Java 8 Tutorial

Friday, December 4, 2020

Converting Between LocalDate and SQL Date In Java 8

1. Overview

In this tutorial, We'll learn how to convert java.time.LocalDate to java.sql Date in java 8 and vice versa.

This is simple to do but when working jpa framework it is bit different to deal with the table column type.

First look at the simple conversions between LocalDate and sql Date objects in java. Next, look at the JPA problem.

Converting Between LocalDate and SQL Date In Java 8


2. Direction conversion between LocalDate and SQL Date


2.1 Convert LocalDate to SQL Date


Use direct method from sql Date.valueOf() method which takes the LocalDate object. So, We can pass the object of LocalDate.now() or LocalDate.of() method.

Look at the below example.
package com.javaprogramto.java8.dates.conversion.sql;

import java.sql.Date;
import java.time.LocalDate;

public class LocalDateToSQLDateExample {

	public static void main(String[] args) {

		// creating current local date using now() method and which will return the
		// curren date.
		LocalDate currentDate = LocalDate.now();

		// LocalDate to SQL date using valueOf() method.
		Date sqlDate = Date.valueOf(currentDate);

		// printing
		System.out.println("With current local date");
		System.out.println("LocalDate : " + currentDate);
		System.out.println("SQL Date : " + sqlDate);
		
		// working with different dates.
		LocalDate pastDate = LocalDate.of(1990, 01, 01);
		LocalDate futureDate = LocalDate.of(2050, 01, 01);
		
		// converting Local dates to sql dates
		Date pastSqlDate = Date.valueOf(pastDate);
		Date futureSqlDate = Date.valueOf(futureDate);
		
		System.out.println("\nWith different local dates");
		System.out.println("Past LocalDate : " + pastDate);
		System.out.println("Past SQL Date : " + pastSqlDate);
		
		System.out.println("Future LocalDate : " + futureDate);
		System.out.println("Future SQL Date : " + futureSqlDate);
	}
}
Output:
With current local date
LocalDate : 2020-12-04
SQL Date : 2020-12-04

With different local dates
Past LocalDate : 1990-01-01
Past SQL Date : 1990-01-01
Future LocalDate : 2050-01-01
Future SQL Date : 2050-01-01

If null value is passed to the Date.valueOf() method, it will throw NullPointerException.
LocalDate nullLocalDate = null;
Date nullDate = Date.valueOf(nullLocalDate);

Output:
Exception in thread "main" java.lang.NullPointerException
	at java.sql/java.sql.Date.valueOf(Date.java:291)
	at com.javaprogramto.java8.dates.conversion.sql.LocalDateToSQLDateExample.main(LocalDateToSQLDateExample.java:38)


2.2 Convert SQL Date to LocalDate


Use toLocalDate() method to convert sql date to time LocalDate in java 8.
package com.javaprogramto.java8.dates.conversion.sql;

import java.sql.Date;
import java.time.LocalDate;

public class SQLDateToLocalDateExample {

	public static void main(String[] args) {

		// Creating sql date
		Date sqlDate = Date.valueOf("2020-12-31");
		
		// converting sql date to localdate using toLocalDate() method.
		LocalDate localDate1 = sqlDate.toLocalDate();

		// printing the local date.
		System.out.println("Local Date 1 : "+localDate1);
	}
}

Output:
Local Date 1 : 2020-12-31

3. JPA Problem Solving AttributeConverter


If you are using the LocalDate as column type in the JPA entity and this is should be having some mapping to the the database columns type. For this type, we assume that sql Date is the right one for the column type. But, database can not recognize the type LocalDate and JPA will map this to blob type rather than java sql Date object.

This is the problem now. To solve this, we should tell to JPA that if there is any column with LocalDate type, convert it into java.sql.Date when inserting into database and convert sql date to LocalDate while retrieving the records from database.

Java persistence api is added with AttributeConverter interface in jdk 1.7.

We need to implement AttributeConverter interface and need to specify the input object type and converted result object type.

This interface has two abstract methods convertToDatabaseColumn() and convertToEntityAttribute().

convertToDatabaseColumn() is to convert the LocalDate to sql date and saves into database.
convertToEntityAttribute() method is executed when fetching the records from database and converts into LocalDate.

We have used Optional inside these two methods to better handle null references to avoid null pointer exception.
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.sql.Date;
import java.time.LocalDate;
import java.util.Optional;

@Converter(autoApply = true)
public class LocalDateConverterExample implements AttributeConverter<LocalDate, Date> {


	// converts LocalDate to sql date using valueOf() method
    @Override
    public Date convertToDatabaseColumn(LocalDate localDate) {
        return Optional.ofNullable(localDate)
          .map(Date::valueOf)
          .orElse(null);
    }

	// converts sql date to LocalDate using toLocalDate() method
    @Override
    public LocalDate convertToEntityAttribute(Date date) {
        return Optional.ofNullable(date)
          .map(Date::toLocalDate)
          .orElse(null);
    }
}


Observe the above code, We've used the @Converter annotation with element autoApply to true. That means apply this conversion is applied to all targeted types by the persistence provider.

But by default this property autoApply is set to false.

If there is more than one converter defined for the same target type, the Convert annotation should be used to explicitly specify which converter to use.

4. Conclusion


In this article, We've seen how to convert between LocalDate and SQL Date in java with example programs.

And also shown how to solve the LocalDate type problem in JPA framework using AttributeConverter interface and @Converter annotation.



No comments:

Post a Comment

Please do not add any spam links in the comments section.