Partner – DBSchema – NPI (tag = SQL)
announcement - icon

DbSchema is a super-flexible database designer, which can take you from designing the DB with your team all the way to safely deploying the schema.

The way it does all of that is by using a design model, a database-independent image of the schema, which can be shared in a team using GIT and compared or deployed on to any database.

And, of course, it can be heavily visual, allowing you to interact with the database using diagrams, visually compose queries, explore the data, generate random data, import data or build HTML5 database reports.

>> Take a look at DBSchema

Course – LS – All

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

>> CHECK OUT THE COURSE

1. Introduction

Spring Dat;u JPA provides a query derivation feature, using which we can derive queries automatically by just following the method name conventions.

In this article, we’ll use the query derivation feature to find entities by one or more columns.

2. Example Setup

For example purposes, we’ll use an Account entity which contains properties related to the user account:

@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 and setters
}

For demo purposes, we’ll also add some sample data to the Accounts table:

userId username password email createdOn lastLogin permission
1 user_admin 737d4251-7ccf-46ce-8227-24cce9be812e [email protected] 2024-02-08 21:26:30.372286 2024-02-09 21:26:30.37229 editor
2 user_admin_1 65cfd915-240c-4f64-8378-27fa1ff9cdf5 [email protected] 2024-02-06 21:26:30.372286 2024-02-07 21:26:30.37229 editor
3 user_admin_2 9b4dca2e-f1d2-4b14-9553-3b8913323b48 [email protected] 2024-02-04 21:26:30.372286 2024-02-06 21:26:30.37229 editor

3. Query Derivation

Query derivation allows the developer to define method names in the repository interface that follow a naming convention, and the framework generates an appropriate query based on that method name.

For example, if we want to search the accounts table by email address, then our method in AccountRepository would look like below:

public interface AccountRepository extends JpaRepository<Account, Integer> {
    Account findByEmail(String email);
}

If we execute findByEmail() on AccountRepository, Spring Data generates the SQL below and executes it against the accounts table:

select a1_0.user_id,a1_0.created_on,a1_0.email,a1_0.last_login,a1_0.password,a1_0.permissions_id,a1_0.username
from accounts a1_0 
where a1_0.email=?

Our test verifies the working of findByEmail() :

@Test
void givenAccountInDb_whenPerformFindByEmail_thenReturnsAccount() {
    String email = "[email protected]";
    Account account = accountRepository.findByEmail(email);
    assertThat(account.getEmail()).isEqualTo(email);
}

4. findBy() With Multiple Columns

We can extend the query derivation feature to add a combination of conditions to get an appropriate result.

Let’s use the AccountRepository interface and write another method for finding Accounts with usernames and emails:

public interface AccountRepository extends JpaRepository<Account, Integer> {
    Account findByUsernameAndEmail(String username, String email);
}

Here’s the generated SQL for the defined method:

select a1_0.user_id,a1_0.created_on,a1_0.email,a1_0.last_login,a1_0.password,a1_0.permissions_id,a1_0.username
from accounts a1_0
where a1_0.username=? and a1_0.email=?

Our test verifies the working of findByUsernameAndEmail():

@Test
void givenAccountInDb_whenPerformFindByUsernameAndEmail_thenReturnsAccount(){
    String email = "[email protected]";
    String username = "user_admin";
    Account account = accountRepository.findByUsernameAndEmail(username, email);
    assertThat(account.getUsername()).isEqualTo(username);
    assertThat(account.getEmail()).isEqualTo(email);
}

We can also use the OR operator to combine two conditions. For example, we can search by either username or email:

public interface AccountRepository extends JpaRepository<Account, Integer> {
    Account findByUsernameOrEmail(String username, String email);
}

Let’s see the generated SQL:

select a1_0.user_id,a1_0.created_on,a1_0.email,a1_0.last_login,a1_0.password,a1_0.permissions_id,a1_0.username
from accounts a1_0
where a1_0.username=? or a1_0.email=?

Now, let’s verify the working of findByUsernameOrEmail():

@Test
void givenAccountInDb_whenPerformFindByUsernameOrEmail_thenReturnsAccount(){
    String email = "[email protected]";
    String username = "user_editor";
    Account account = accountRepository.findByUsernameOrEmail(username, email);
    assertThat(account.getUsername()).isNotEqualTo(username);
    assertThat(account.getEmail()).isEqualTo(email);
}

We can use the collection of input in findBy() method. For example, to find all accounts that exist in the list of emails or list of usernames, we can write a method in AccountRepository:

public interface AccountRepository extends JpaRepository<Account, Integer> {
    List<Account> findByUsernameInOrEmailIn(List<String> usernames, List<String> emails);
}

Let’s check out the generated SQL:

select a1_0.user_id,a1_0.created_on,a1_0.email,a1_0.last_login,a1_0.password,a1_0.permissions_id,a1_0.username 
from accounts a1_0 
where a1_0.username in (?,?) or a1_0.email in (?,?,?)

Our test confirms the working of findByUsernameInOrEmailIn():

@Test
void givenAccountInDb_whenPerformFindByUsernameInOrEmailIn_thenReturnsAccounts(){
    List<String> emails = List.of("[email protected]", "[email protected]", "[email protected]");
    List<String> usernames = List.of("user_editor", "user_admin");
    List<Account> byUsernameInOrEmailIn = accountRepository.findByUsernameInOrEmailIn(usernames, emails);
    assertThat(byUsernameInOrEmailIn.size()).isEqualTo(1);
    assertThat(byUsernameInOrEmailIn.get(0).getEmail()).isEqualTo("[email protected]");
}

5. Conclusion

In this tutorial, we discussed the query derivation feature of Spring Data and used it to find entities in a table. We also explored the usage of various input parameters for finding entities with conditions such as AND and OR.

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

Course – LSD (cat=Persistence)

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

>> CHECK OUT THE COURSE
Course – LS – All

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

>> CHECK OUT THE COURSE
res – Persistence (eBook) (cat=Persistence)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.