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.
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.