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.

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

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

In distributed systems, managing multi-step processes (e.g., validating a driver, calculating fares, notifying users) can be difficult. We need to manage state, scattered retry logic, and maintain context when services fail.

Dapr Workflows solves this via Durable Execution which includes automatic state persistence, replaying workflows after failures and built-in resilience through retries, timeouts and error handling.

In this tutorial, we'll see how to orchestrate a multi-step flow for a ride-hailing application by integrating Dapr Workflows and Spring Boot:

>> Dapr Workflows With PubSub

1. Overview

The Spring Data JPA implementation provides repository support for the Jakarta Persistence API for managing persistence, as well as object-relational mapping and functions.

In this tutorial, we’ll explore different ways to count the number of rows in a table using the JPA.

2. Entity Classes

For our example, we’ll use the Account entity, which has a one-to-one relation with the Permission entity:

@Entity
@Table(name="ACCOUNTS")
public class Account {
    @Id
    @GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "accounts_seq")
    @SequenceGenerator(name = "accounts_seq", sequenceName = "accounts_seq", allocationSize = 1)
    @Column(name = "user_id")
    private int userId;
    private String username;
    private String password;
    private String email;
    private Timestamp createdOn;
    private Timestamp lastLogin;
    
    @OneToOne
    @JoinColumn(name = "permissions_id")
    private Permission permission;

   // getters , setters
}

Permission belongs to the account entity:

@Entity
@Table(name="PERMISSIONS")
public class Permission {
    @Id
    @GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "permissions_id_sq")
    @SequenceGenerator(name = "permissions_id_sq", sequenceName = "permissions_id_sq", allocationSize = 1)
    private int id;

    private String type;

    // getters , setters
}

3. Using the JPA Repository

Spring Data JPA provides a repository interface that can be extended, which offers out-of-the-box query methods and derived query methods, such as findAll(), findBy(), save(), saveAndFlush(), count(), countBy(), delete(), and deleteAll().

We’ll define the AccountRepository interface that extends the JpaRepository interface, so that will get access to the count methods.

If we need to count based on one or more conditions, such as countByFirstname(), countByPermission(), or countByPermissionAndCredtedOnGreaterThan(), all we need is the name of the method in the AccountRepository interface, and then query derivation will take care of defining the appropriate SQL for it:

public interface AccountRepository extends JpaRepository<Account, Integer> { 
    long countByUsername(String username);
    long countByPermission(Permission permission); 
    long countByPermissionAndCreatedOnGreaterThan(Permission permission, Timestamp ts)
}

In the below examples, we’ll use AccountRepository in the logic class to perform the count operation.

3.1. Count All the Rows in the Table

We’ll define a logic class where we inject AccountRepository. For a simple row count() operation, we can use accountRepository.count(), and we’ll get the result:

@Service
public class AccountStatsLogic {
    @Autowired
    private AccountRepository accountRepository;

    public long getAccountCount(){
        return accountRepository.count();
    }
}

3.2. Count Result Rows Based on the Single Condition

As we defined above, AccountRepository contains the method names countByPermission and countByUsername, so Spring Data JPA query derivation will derive the query for these methods.

We can use these methods for the conditional count in the logic class, and we’ll get the result:

@Service
public class AccountStatsLogic {
    @Autowired
    private AccountRepository accountRepository;

    @Autowired
    private PermissionRepository permissionRepository;
    
    public long getAccountCountByUsername(){
        String username = "user2";
        return accountRepository.countByUsername(username);
    }
    
    public long getAccountCountByPermission(){
        Permission permission = permissionRepository.findByType("reader");
        return accountRepository.countByPermission(permission);
    }
}

3.3. Count Result Rows Based on the Multiple Conditions

We can also include multiple conditions in our query derivation, like the one below, where we include Permission and CreatedOnGreaterThan:

@Service
public class AccountStatsLogic {
    @Autowired
    private AccountRepository accountRepository;

    @Autowired
    private PermissionRepository permissionRepository;
    
    public long getAccountCountByPermissionAndCreatedOn() throws ParseException {
        Permission permission = permissionRepository.findByType("reader");
        Date parsedDate = getDate();
        return accountRepository.countByPermissionAndCreatedOnGreaterThan(permission, new Timestamp(parsedDate.getTime()));
    }
}

4. Using CriteriaQuery

The next approach to counting the rows in JPA is to use the CriteriaQuery interface. This interface allows us to write queries in an Object oriented way, so that we can skip the knowledge of writing raw SQL queries.

It requires us to construct a CriteriaBuilder object, which then helps us construct CriteriaQuery. Once CriteriaQuery is ready, we can use the createQuery method from entityManager to execute the query and get the result.

4.1. Count All the Rows

Now when we construct the query using CriteriaQuery, we can define the select query to count:

public long getAccountsUsingCQ() throws ParseException {
    // creating criteria builder and query
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Long> criteriaQuery = builder.createQuery(Long.class);
    Root<Account> accountRoot = criteriaQuery.from(Account.class);
     
    // select query
    criteriaQuery.select(builder.count(accountRoot));
     
     // execute and get the result
    return entityManager.createQuery(criteriaQuery).getSingleResult();
}

4.2. Count Result Rows Based on the Single Condition

We can also extend the select query to include where conditions to filter our query on certain conditions.. We can add a Predicate to our builder instance and pass it to the where clause:

public long getAccountsByPermissionUsingCQ() throws ParseException {
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Long> criteriaQuery = builder.createQuery(Long.class);
    Root<Account> accountRoot = criteriaQuery.from(Account.class);
        
    List<Predicate> predicateList = new ArrayList<>(); // list of predicates that will go in where clause
    predicateList.add(builder.equal(accountRoot.get("permission"), permissionRepository.findByType("admin")));

    criteriaQuery
      .select(builder.count(accountRoot))
      .where(builder.and(predicateList.toArray(new Predicate[0])));

    return entityManager.createQuery(criteriaQuery).getSingleResult();
}

4.3. Count Result Rows Based on the Multiple Conditions

In our predicate, we can add multiple conditions for filtering our query. The builder instance provides conditional methods, such as equal() and greaterThan(), to support conditions on queries:

public long getAccountsByPermissionAndCreateOnUsingCQ() throws ParseException {
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Long> criteriaQuery = builder.createQuery(Long.class);
    Root<Account> accountRoot = criteriaQuery.from(Account.class);
    
    List<Predicate> predicateList = new ArrayList<>();
    predicateList.add(builder.equal(accountRoot.get("permission"), permissionRepository.findByType("reader")));
    predicateList.add(builder.greaterThan(accountRoot.get("createdOn"), new Timestamp(getDate().getTime())));

    criteriaQuery
      .select(builder.count(accountRoot))
      .where(builder.and(predicateList.toArray(new Predicate[0])));

    return entityManager.createQuery(criteriaQuery).getSingleResult();
}

5. Using JPQL Query

The next approach to performing count is to use JPQL. JPQL queries work against entities, instead of databases directly, that more or less look like SQL queries. We can always write a JPQL query that can count rows in JPA.

5.1. Count All the Rows

The entityManager provides a createQuery() method that takes the JPQL query as an argument, and executes that on the database:

public long getAccountsUsingJPQL() throws ParseException {
    Query query = entityManager.createQuery("SELECT COUNT(*) FROM Account a");
    return (long) query.getSingleResult();
}

5.2. Count Result Rows Based on the Single Condition

In JPQL query, we can include WHERE conditions, as we do in raw SQL, to filter queries and count the returned rows:

public long getAccountsByPermissionUsingJPQL() throws ParseException {
    Query query = entityManager.createQuery("SELECT COUNT(*) FROM Account a WHERE a.permission = ?1");
    query.setParameter(1, permissionRepository.findByType("admin"));
    return (long) query.getSingleResult();
}

5.3. Count Result Rows Based on the Multiple Conditions

In JPQL query, we can include multiple conditions in the WHERE clause, as we do in raw SQL, to filter queries and count the returned rows:

public long getAccountsByPermissionAndCreatedOnUsingJPQL() throws ParseException {
    Query query = entityManager.createQuery("SELECT COUNT(*) FROM Account a WHERE a.permission = ?1 and a.createdOn > ?2");
    query.setParameter(1, permissionRepository.findByType("admin"));
    query.setParameter(2, new Timestamp(getDate().getTime()));
    return (long) query.getSingleResult();
}

6. Count the Number of Rows With Hibernate Criteria

For applications using older versions of Hibernate or cases where the Criteria API is still in place, Hibernate offers its own Criteria interface for building dynamic queries. This can be a helpful alternative for counting rows in cases where JPA’s CriteriaQuery API isn’t being used.

Although Hibernate’s Criteria API is deprecated in favor of the CriteriaQuery API, it remains useful in many legacy applications.

In this example, we’ll use two entities, Foo and Bar, which are associated through a many-to-one relationship. Each Foo object is linked to a specific Bar object, and we’ll count the number of Foo objects based on conditions applied to both the Foo and its associated Bar.

6.1. Count All Rows in the Table

Using the Hibernate Criteria API, we can count all rows in a table by setting a Projection on the Criteria. In this example, we’ll configure a Projections.rowCount() to retrieve a count of rows in the Foo entity:

public long countAllRowsUsingHibernateCriteria() {
    Session session = entityManager.unwrap(Session.class);
    Criteria criteria = session.createCriteria(Foo.class);
    criteria.setProjection(Projections.rowCount());
    Long count = (Long) criteria.uniqueResult();
    return count != null ? count : 0L;
}

In the countAllRowsUsingHibernateCriteria() method, we first obtain a Hibernate Session from the EntityManager by calling unwrap() method. Then, we create a Criteria instance for our entity, using Projections.rowCount() to specify that we want a count of all rows. Finally, we call uniqueResult() to retrieve the single count result from the query.

6.2. Count Rows Based on a Single Condition

To count rows based on a single condition, we can add a restriction to the Criteria to filter the results. In this example, we count the number of Foo objects based on a specific Bar object name:

public long getFooCountByBarNameUsingHibernateCriteria(String barName) {
    Session session = entityManager.unwrap(Session.class);
    Criteria criteria = session.createCriteria(Foo.class);
    criteria.createAlias("bar", "b");
    criteria.add(Restrictions.eq("b.name", barName));
    criteria.setProjection(Projections.rowCount());
    return (Long) criteria.uniqueResult();
}

In this code, we use createAlias() to create an alias “b” for the bar field. Then, we add a restriction using Restrictions.eq(), setting it to filter rows by the specified barName. Finally, we use Projections.rowCount() to indicate that we want a count of rows that match this condition and call uniqueResult() to retrieve the result.

6.3. Count Rows Based on Multiple Conditions

We can add several Restrictions to the Criteria to count rows based on multiple conditions. In this example, we count Foo rows where the associated Bar‘s name is a specific value, and the Foo‘s name matches a specified value:

public long getFooCountByBarNameAndFooNameUsingHibernateCriteria(String barName, String fooName) {
    Session session = entityManager.unwrap(Session.class);
    Criteria criteria = session.createCriteria(Foo.class);
    criteria.createAlias("bar", "b");
    criteria.add(Restrictions.eq("b.name", barName));
    criteria.add(Restrictions.eq("name", fooName));
    criteria.setProjection(Projections.rowCount());
    return (Long) criteria.uniqueResult();
}

Similar to the previous example, we use createAlias() to create an alias for the bar field. This time, we add two restrictions: one with Restrictions.eq() to filter rows by bar.name, and another with Restrictions.eq() to filter rows where the Foo object’s name matches the specified value. We then set Projections.rowCount() to count the rows that match these conditions and call uniqueResult() to retrieve the result.

7. Conclusion

In this article, we learned different approaches to counting the number of rows in JPA. The specifications, such as CriteriaBuilder and Spring Data JPA Query derivation, help us write count queries easily with different conditions.

While CriteriaQuery & Spring Data JPA query derivation help us build queries that don’t require raw SQL knowledge, in some use cases, we may want to write raw SQL using JPQL.

As always, the example code is available on GitHub. The code for Section 6 can be found in a different module, available here.

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.

eBook Jackson – NPI EA – 3 (cat = Jackson)