eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

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

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

Regression testing is an important step in the release process, to ensure that new code doesn't break the existing functionality. As the codebase evolves, we want to run these tests frequently to help catch any issues early on.

The best way to ensure these tests run frequently on an automated basis is, of course, to include them in the CI/CD pipeline. This way, the regression tests will execute automatically whenever we commit code to the repository.

In this tutorial, we'll see how to create regression tests using Selenium, and then include them in our pipeline using GitHub Actions:, to be run on the LambdaTest cloud grid:

>> How to Run Selenium Regression Tests With GitHub Actions

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

1. Introduction

When working with databases in JPA, it’s common to store timestamps in a database table, such as createdAt or updatedAt. But sometimes we only have a LocalDate, such as when a user selects a date from a calendar. In that case, we may want to find all records that fall on that date, regardless of their time.

If we try to compare a LocalDateTime field directly with a LocalDate value, the query won’t match anything because the two data types are not the same. In this tutorial, we’ll explore several ways to query a LocalDateTime field using a LocalDate value in JPA.

2. Understanding the Core Problem

Suppose we have an entity with a field of type LocalDateTime:

@Entity
public class MyClass {
    @Id
    private UUID id;

    private LocalDateTime createdAt;

    // Getters and setters
}

And a repository defined like this:

@Service
public interface IRepository extends CrudRepository<MyClass, UUID> {
    void deleteByCreatedAt(LocalDate createdAt);
}

At first glance, this looks valid, as the method name follows Spring Data conventions, and createdAt seems to match the field name. However, when we call it with a plain LocalDate:

repository.deleteByCreatedAt(LocalDate.of(2024, 01, 15));

JPA throws an exception:

org.springframework.dao.InvalidDataAccessApiUsageException:
Parameter value [2024-01-15] did not match expected type [java.time.LocalDateTime (n/a)];

This error happens because the createdAt column in the database is of type LocalDateTime, but the repository method receives a LocalDate. Spring Data JPA doesn’t automatically convert between the two, since one includes a time component while the other does not.

A LocalDateTime contains both date and time information (e.g., 2024-01-15T14:30:45), while a LocalDate only contains date information (e.g., 2024-01-15).

So when we run a query like:

WHERE created_at = '2024-01-15'

The database looks for a timestamp that exactly matches that value — including the time. Since actual timestamps usually have hours, minutes, and seconds, this equality comparison finds no results.

To correctly find all records from that day, we need to look for all createdAt values that fall within the entire date range — from midnight (2024-01-15T00:00:00) up to but not including the next midnight (2024-01-16T00:00:00). This required us to convert the LocalDate into a LocalDateTime range.

3. Project Setup

To use JPA in a Spring Boot project, we need to include the spring-boot-starter-data-jpa dependency along with a database driver. In this tutorial, we’ll use H2 to illustrate our examples.

Add the following dependencies to our pom.xml file:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

3.1. Defining the Entity

Next, we’ll define a simple entity to represent our database table.

Let’s call it an Event. It will have an ID, a name, and a createdAt field of type LocalDateTime:

@Entity
@Table(name = "events")
public class Event {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;

    public Event() {}

    public Event(String name, LocalDateTime createdAt) {
        this.name = name;
        this.createdAt = createdAt;
    }

    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }

    // Getters and setters

}

This entity maps directly to a table named events in the database. The @Entity annotation tells JPA that this class should be treated as a managed entity, while the @Table(name = “events”) annotation specifies the exact table name to use.

The createdAt field uses the LocalDateTime type, which stores both the date and time of creation—for example, a value like 2025-10-12T14:35:20. The @PreUpdate annotations automatically handle timestamp population.

3.2. Preparing Sample Data

To make the examples and test cases easier to follow, let’s also prepare some sample data in an H2 data file. We can use the data.sql file under src/main/resources — Spring Boot will automatically execute it at startup.

Create a file named data.sql and add the following:

INSERT INTO events (name, created_at, updated_at) VALUES
('Morning Meeting', '2025-10-12T09:00:00', '2025-10-12T09:00:00'),
('Lunch Discussion', '2025-10-12T12:30:00', '2025-10-12T12:30:00'),
('Evening Review', '2025-10-12T18:45:00', '2025-10-12T18:45:00'),
('Next Day Planning', '2025-10-13T10:00:00', '2025-10-13T10:00:00');

To ensure it still runs after Hibernate has created the events table, we must add this line to our application.properties:

spring.jpa.defer-datasource-initialization=true

4. Query by Date Range

The most reliable way to query a LocalDateTime field using a LocalDate value is by performing a range query. Instead of comparing equality between the two types, we convert the LocalDate into a start and end boundary that represents the entire day.

This means we’ll fetch all records where createdAt is greater than or equal to the start of the day, and less than the start of the next day.

We start by defining a query method in our JPA repository:

public interface EventRepository extends JpaRepository<Event, Long> {
    List<Event> findByCreatedAtBetween(LocalDateTime start, LocalDateTime end);
}

This method automatically generates a query to fetch all records where createdAt falls between the two given timestamps.

Now, we can easily query events for a specific date by converting a LocalDate into a range of LocalDateTime values:

LocalDate date = LocalDate.of(2025, 10, 12);
LocalDateTime startOfDay = date.atStartOfDay();
LocalDateTime endOfDay = date.plusDays(1).atStartOfDay();

List results = eventRepository.findByCreatedAtBetween(startOfDay, endOfDay);
assertEquals(3, results.size());

In this example, the startOfDay represents midnight (2025-10-12T00:00:00) and the endOfDay represents midnight of the next day (2025-10-13T00:00:00).
By using these two boundary values, the query captures all events created on October 12th, no matter what the exact time was.

Under the hood, Spring Data JPA generates an SQL query similar to this:

SELECT * FROM events 
WHERE created_at >= '2025-10-12T00:00:00'
  AND created_at < '2025-10-13T00:00:00';

This method is efficient and database-independent. It also allows the database to make use of indexes on the created_at column, which keeps the query fast even when the table grows large.

Alternatively, if we prefer to be more explicit about the range boundaries, we can define the method as:

List<Event> findByCreatedAtGreaterThanEqualAndCreatedAtLessThan(
  LocalDateTime start,
  LocalDateTime end
);

This method produces the same result as the Between version, but makes it clearer that the lower bound is inclusive (>=) and the upper bound is exclusive (<):

List<Event> results = eventRepository
  .findByCreatedAtGreaterThanEqualAndCreatedAtLessThan(startOfDay, endOfDay);
assertEquals(3, results.size());

5. Using JPQL @Query and Database Functions

Another way to query a LocalDateTime field using a LocalDate value is by using JPQL @Query and database-specific functions. Some databases like MySQL, PostgreSQL, and H2 provide a built-in DATE() function that extracts only the date part from a timestamp, ignoring the time portion.

This allows us to directly compare the extracted date with our LocalDate value.

In this approach, we define a custom query using the @Query annotation:

@Query("SELECT e FROM Event e WHERE FUNCTION('DATE', e.createdAt) = :date")
List<Event> findByDate(@Param("date") LocalDate date);

In this example, FUNCTION(‘DATE’, e.createdAt) tells JPA to call the DATE() function in the underlying database. This converts the timestamp stored in createdAt into a plain date (for example, converting 2025-10-12T14:30:45 into 2025-10-12).

The comparison then becomes straightforward because both sides of the condition are DATE values.

To execute the query, we simply pass in a LocalDate value:

LocalDate date = LocalDate.of(2025, 10, 12);
List<Event> events = eventRepository.findByDate(date);
assertEquals(3, results.size());

This will generate a SQL query similar to:

SELECT * FROM events
WHERE DATE(created_at) = '2025-10-12';

This approach is concise and often easier to read than the range-based method. However, not all databases support the same DATE() functions; for example, Oracle uses TRUNC() instead.

Furthermore, using a function directly on the column DATE(created_at) prevents the database from using indexes efficiently.

6. Using the Criteria API for Dynamic Queries

Sometimes we want to build queries at runtime rather than hard-coding repository methods. For example, we might have a search screen where users pick a date, and we need to fetch all records whose createdAt falls on that date.

The Criteria API lets us do this programmatically while still following the same logic as our range-based approach:

@Repository
public class EventCriteriaRepository {
    @PersistenceContext
    private EntityManager entityManager;

    public List<Event> findByCreatedDate(LocalDate date) {
        LocalDateTime startOfDay = date.atStartOfDay();
        LocalDateTime endOfDay   = date.plusDays(1).atStartOfDay();

        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<Event> cq = cb.createQuery(Event.class);
        Root<Event> root = cq.from(Event.class);

        cq.select(root).where(
          cb.between(root.get("createdAt"), startOfDay, endOfDay)
        );

        return entityManager.createQuery(cq).getResultList();
    }
}

In the example, we first convert the LocalDate into two LocalDateTime boundaries:

startOfDay → 00:00:00 of the selected date
endOfDay → 00:00:00 of the next day

Then we use the CriteriaBuilder to create a query that selects all Event records whose createdAt lies between those two timestamps. This is effectively the same as running:

SELECT * FROM events
WHERE created_at >= '2025-10-12T00:00:00'
  AND created_at <  '2025-10-13T00:00:00';

To execute this, we can simply pass the LocalDate value:

LocalDate date = LocalDate.of(2025, 10, 12);
List<Event> results = eventCriteriaRepository.findByCreatedDate(date);
assertEquals(3, results.size());

The Criteria API keeps everything type-safe, which is useful when we want to add more predicates later (for example, filtering by event name or status) while still handling the LocalDate and LocalDateTime conversion correctly.

7. Using Native SQL Query

In some cases, we may already have a complex query written in SQL, or we need to use a database-specific function that JPQL doesn’t support. Spring Data JPA allows us to write SQL statements using the @Query annotation with nativeQuery=true:

public interface EventRepository extends JpaRepository<Event, Long> {
    @Query(
      value = "SELECT * FROM events " +
        "WHERE created_at >= :startOfDay " +
        "AND created_at < :endOfDay",
      nativeQuery = true
    )
    List<Event> findByDateRangeNative(
      @Param("startOfDay") LocalDateTime startOfDay,
      @Param("endOfDay") LocalDateTime endOfDay
    );
}

The nativeQuery = true flag tells Spring Data JPA that this query should be sent directly to the database engine without translation. By using native SQL, we get full control over the executed statement.

8. Conclusion

In this article, we learned how to query LocalDateTime fields using a LocalDate value in JPA. We explored multiple approaches, such as simple range queries, JPQL functions, and dynamic Criteria API queries.

As always, the source code is available over on GitHub.

Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

Course – LSD – NPI (cat=JPA)
announcement - icon

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

>> CHECK OUT THE COURSE

eBook Jackson – NPI EA – 3 (cat = Jackson)
4 Comments
Oldest
Newest
Inline Feedbacks
View all comments