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

Java Persistence API (JPA) acts as a bridge between Java objects and relational databases, allowing us to persist and retrieve data seamlessly. In this tutorial, we’ll explore various strategies and techniques to effectively refresh and fetch entities after saving operations in JPA.

2. Understanding Entity Management in Spring Data JPA

In Spring Data JPA, entity management revolves around the JpaRepository interface, which serves as the primary mechanism for interacting with the database. Through the JpaRepository interface, which extends CrudRepository, Spring Data JPA offers a robust set of methods for entity persistence, retrieval, updating, and deletion.

Furthermore, the entityManager is automatically injected into these repository interfaces by the Spring container. This component is an integral part of the JPA infrastructure embedded within Spring Data JPA, facilitating interaction with the underlying persistence context and the execution of JPA queries.

2.1. Persistence Context

One crucial component within JPA is the persistence context. Imagine this context as a temporary holding area where JPA manages the state of retrieved or created entities.

It ensures that:

  • Entities are unique: Only one instance of an entity with a specific primary key exists within the context at any given time.
  • Changes are tracked: The EntityManager keeps track of any modifications made to entity properties within the context.
  • Data consistency is maintained: The EntityManager synchronizes changes made within the context with the underlying database during transactions.

2.2. Lifecycle of JPA Entities

There are four distinct lifecycle stages of JPA entities: New, Managed, Removed, and Detached.

When we create a new entity instance using the entity’s constructor, it is in the “New” state. We can verify this by checking if the entity’s ID (primary key) is null:

Order order = new Order();
if (order.getId() == null) {
    // Entity is in the "New" state
}

After we persist the entity using a repository’s save() method, it transitions to the “Managed” state. We can verify this by checking if the saved entity exists in the repository:

Order savedOrder = repository.save(order);
if (repository.findById(savedOrder.getId()).isPresent()) {
    // Entity is in the "Managed" state
}

When we call the repository’s delete() method on a managed entity, it transitions to the “Removed” state. We can verify this by checking if the entity is no longer present in the database after deletion:

repository.delete(savedOrder);
if (!repository.findById(savedOrder.getId()).isPresent()) {
    // Entity is in the "Removed" state
}

Lastly, once the entity is detached using the repository’s detach() method, the entity is no longer associated with the persistence context. Changes made to a detached entity won’t be reflected in the database unless explicitly merged back into the managed state. We can verify this by attempting to modify the entity after detaching it:

repository.detach(savedOrder);
// Modify the entity
savedOrder.setName("New Order Name");

If we call save() on a detached entity, it re-attaches the entity to the persistence context and persists the changes to the database upon flushing the persistence context.

3. Saving Entities with Spring Data JPA

When we invoke save(), Spring Data JPA schedules the entity for insertion into the database upon transaction commit. It adds the entity to the persistence context, marking it as managed.

Here’s a simple code snippet demonstrating how to use the save() method in Spring Data JPA to persist an entity:

Order order = new Order();
order.setName("New Order Name");

repository.save(order);

However, it’s important to note that invoking save() doesn’t immediately trigger a database insert operation. Instead, it merely transitions the entity to the managed state within the persistence context. Thus, if other transactions read data from the database before our transaction commits, they might retrieve outdated data that doesn’t include the changes we’ve made but not yet committed.

To ensure that the data remains up-to-date, we can employ two approaches: fetching and refreshing.

4. Fetching Entities in Spring Data JPA

When we fetch an entity, we don’t discard any modifications made to it within the persistence context. Instead, we simply retrieve the entity’s data from the database and add it to the persistence context for further processing.

4.1. Using findById()

Spring Data JPA repositories offer convenient methods like findById() for retrieving entities. These methods always fetch the latest data from the database, regardless of the entity’s state within the persistence context. This approach simplifies entity retrieval and eliminates the need to manage the persistence context directly.

Order order = repository.findById(1L).get();

4.2. Eager vs. Lazy Fetching

In eager fetching, all related entities associated with the main entity are retrieved from the database at the same time as the main entity. By setting fetch = FetchType.EAGER on the orderItems collection, we instruct JPA to eagerly fetch all associated OrderItem entities when retrieving an Order:

@Entity
public class Order {
    @Id
    private Long id;

    @OneToMany(mappedBy = "order", fetch = FetchType.EAGER)
    private List<OrderItem> orderItems;
}

This means that after the findById() call, we can directly access the orderItems list within the order object and iterate through the associated OrderItem entities without requiring any additional database queries:

Order order = repository.findById(1L).get();

// Accessing OrderItems directly after fetching the Order
if (order != null) {
    for (OrderItem item : order.getOrderItems()) {
        System.out.println("Order Item: " + item.getName() + ", Quantity: " + item.getQuantity());
    }
}

On the other hand, by setting fetch = FetchType.LAZY, related entities will not retrieved from the database until they are explicitly accessed within the code:

@Entity
public class Order {
    @Id
    private Long id;

    @OneToMany(mappedBy = "order", fetch = FetchType.LAZY)
    private List<OrderItem> orderItems;
}

When we call order.getOrderItems(), a separate database query is executed to fetch the associated OrderItem entities for that order. This additional query is only triggered because we explicitly accessed the orderItems list:

Order order = repository.findById(1L).get();

if (order != null) {
    List<OrderItem> items = order.getOrderItems(); // This triggers a separate query to fetch OrderItems
    for (OrderItem item : items) {
        System.out.println("Order Item: " + item.getName() + ", Quantity: " + item.getQuantity());
    }
}

4.3. Fetching with JPQL

Java Persistence Query Language (JPQL) allows us to write SQL-like queries that target entities instead of tables. It provides flexibility for retrieving specific data or entities based on various criteria.

Let’s see an example of fetching orders by customer name and with the order date falling within a specified range:

@Query("SELECT o FROM Order o WHERE o.customerName = :customerName AND 
  o.orderDate BETWEEN :startDate AND :endDate")
List<Order> findOrdersByCustomerAndDateRange(@Param("customerName") String customerName, 
  @Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate);

4.4. Fetching with Criteria API

The Criteria API in Spring Data JPA provides a reliable and flexible method to create queries dynamically. It allows us to construct complex queries safely using method chaining and criteria expressions, ensuring that our queries are error-free at compile time.

Let’s consider an example where we use the Criteria API to fetch orders based on a combination of criteria, such as customer name and order date range:

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Order> criteriaQuery = criteriaBuilder.createQuery(Order.class);
Root<Order> root = criteriaQuery.from(Order.class);

Predicate customerPredicate = criteriaBuilder.equal(root.get("customerName"), customerName);
Predicate dateRangePredicate = criteriaBuilder.between(root.get("orderDate"), startDate, endDate);

criteriaQuery.where(customerPredicate, dateRangePredicate);

return entityManager.createQuery(criteriaQuery).getResultList();

5. Refreshing Entities with Spring Data JPA

Refreshing entities in JPA ensures that the in-memory representation of entities in the application stays synchronized with the latest data stored in the database. When other transactions modify or update entities, the data within the persistence context might become outdated. Refreshing entities allow us to retrieve the most recent data from the database, preventing inconsistencies and maintaining data accuracy.

5.1. Using refresh()

In JPA, we achieve entity refreshing using the refresh() method provided by the EntityManager. Invoking refresh() on a managed entity discards any modifications made to the entity within the persistence context. It reloads the entity’s state from the database, effectively replacing any modifications made since the entity was last synchronized with the database.

However, it’s important to note that Spring Data JPA repositories do not offer a built-in refresh() method.

Here’s how to refresh an entity using the EntityManager:

@Autowired
private EntityManager entityManager;

entityManager.refresh(order);

5.2. Handling OptimisticLockException

The @Version annotation in Spring Data JPA serves the purpose of implementing optimistic locking. It helps ensure data consistency when multiple transactions might try to update the same entity concurrently. When we use @Version, JPA automatically creates a special field (often named version) on our entity class.

This field stores an integer value representing the version of the entity in the database:

@Entity
public class Order {
    @Id
    @GeneratedValue
    private Long id;
    
    @Version
    private Long version;
}

When retrieving an entity from the database, JPA actively fetches its version. Upon updating the entity, JPA compares the version of the entity in the persistence context with the version stored in the database. If the versions of the entity differ, it indicates that another transaction has modified the entity, potentially leading to data inconsistency.

In such cases, JPA throws an exception, often an OptimisticLockException, to indicate the potential conflict. Therefore, we can call the refresh() method within the catch block to reload the entity’s state from the database.

Let’s see a brief demonstration of how this approach works:

Order order = orderRepository.findById(orderId)
  .map(existingOrder -> {
      existingOrder.setName(newName);
      return existingOrder;
  })
  .orElseGet(() -> {
      return null;
  });

if (order != null) {
    try {
        orderRepository.save(order);
    } catch (OptimisticLockException e) {
        // Refresh the entity and potentially retry the update
        entityManager.refresh(order);
        // Consider adding logic to handle retries or notify the user about the conflict
    }
}

Additionally, it’s worth noting that refresh() may throw javax.persistence.EntityNotFoundException if the entity being refreshed has been removed from the database by another transaction since it was last retrieved.

6. Conclusion

In this article, we learned the distinction between refreshing and fetching entities in Spring Data JPA. Fetching involves retrieving the latest data from the database when needed. Refreshing involves updating the entity’s state in the persistence context with the most recent data from the database.

By utilizing these approaches strategically, we can maintain data consistency and ensure that all transactions operate on the latest data.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
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)