Spring Data JPA

Spring Data JPA is a popular Spring Framework projects, and simplifies creating JPA-based repositories by reducing the boilerplate code required to implement data access layers. It provides enhanced support for JPA-based data access using Spring annotation driven programming.

Spring Data JPA provides out-of-the-box support for PostgreSQL-compliant databases. This includes auto-reconfiguration support for creating the data source objects based on the database driver in the classpath. YugabyteDB provides complete support for Spring Data JPA using the PostgreSQL dialect. Spring Data JPA repositories can be used to read and write data to YugabyteDB clusters.

This document describes the fundamentals of using Spring Data JPA with YugabyteDB to create Spring Boot applications.

Quick start

Learn how to establish a connection to YugabyteDB database and begin basic CRUD operations using the steps in Java ORM example application.

Project dependencies

Spring Data JPA can be used with both YugabyteDB JDBC driver and the upstream PostgreSQL JDBC driver.

Maven dependency

Add the following dependencies for Spring Data JPA with YugabyteDB JDBC Driver.

<dependencies>
  <dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-jpa</artifactId>
    <version>2.6.3</version>
  </dependency>
  <dependency>
    <groupId>com.yugabyte</groupId>
    <artifactId>jdbc-yugabytedb</artifactId>
    <version>42.7.3-yb-1</version>
  </dependency>
<dependencies>

If you're planning to use the PostgreSQL JDBC driver, use the following dependencies:

<dependencies>
  <dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-jpa</artifactId>
    <version>2.6.3</version>
  </dependency>
  <dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.2.14</version>
  </dependency>
<dependencies>

Fundamentals

Learn how to perform common tasks required for developing Spring Boot applications using Spring Data JPA with YugabyteDB YSQL API.

Connect to YugabyteDB Database using Spring Data JPA

The Spring Data JPA project provides number of spring.datasource.* properties that can be customized to configure the data source and transaction behavior of Spring Boot applications.

Configure the Spring Boot application to connect to a YugabyteDB Cluster using the following properties in the application.properties file:

YugabyteDB JDBC driver

spring property Description Value
spring.datasource.url JDBC URL jdbc:yugabytedb://127.0.0.1:5433/yugabyte?load-balance=true
spring.datasource.username user for connecting to the database yugabyte
spring.datasource.password password for connecting to the database yugabyte
spring.datasource.driver-class-name JDBC driver classname com.yugabyte.Driver
spring.datasource.hikari.minimum-idle JDBC connection idle timeout 5
spring.datasource.hikari.maximum-pool-size Maximum number of DB connections in the Pool 20
spring.datasource.hikari.auto-commit Transaction commit behavior false

PostgreSQL JDBC driver

spring property Description Value
spring.datasource.url JDBC URL jdbc:postgresql://localhost:5433/yugabyte
spring.datasource.username user for connecting to the database yugabyte
spring.datasource.password password for connecting to the database yugabyte
spring.datasource.hikari.minimum-idle JDBC connection idle timeout 5
spring.datasource.hikari.maximum-pool-size Maximum number of DB connections in the Pool 20
spring.datasource.hikari.auto-commit Transaction commit behavior false

Create table

Spring Data JPA uses Hibernate ORM for handling creation of the database tables based on the domain objects configured in the Spring Boot application. Java POJOs annotated with @Table and @Entity are mapped to the corresponding YugabyteDB table.

For example:

@Entity
@Table(name = "users")
public class User {

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 @Column(columnDefinition = "serial")
 private Long userId;

...

This domain object maps to the users table on the database, which has userId as the primary key and an auto incrementing type.

Spring Boot applications can be configured to determine whether tables should be created on application startup or not. Add the following property in application.properties to configure the database table creation behavior.

# Hibernate ddl auto (create, create-drop, validate, update, none).
spring.jpa.hibernate.ddl-auto=create

For production environments, it's good practice to disable database table creation on startup. To prevent table creation on startup, set the property to none.

Read and write data

Enable JPA repositories

Spring Data JPA repositories provide support for CRUDRepository, JPARepository, and PagingAndSortingRepository. By enabling these repositories, Spring Boot applications get access to data access methods out of the box. For more information, refer to the Spring Data JPA reference documentation.

public interface CrudRepository<T, ID> extends Repository<T, ID> {

  <S extends T> S save(S entity);

  Optional<T> findById(ID primaryKey);

  Iterable<T> findAll();

  long count();

  void delete(T entity);

  boolean existsById(ID primaryKey);

  // … more functionality omitted.
}

Spring Boot applications can be configured to enable these repositories by using the following Java configuration class.

import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@EnableJpaRepositories
class Config {  }

Insert data

To write data to YugabyteDB, implement the repository for each domain object.

For example:

import org.springframework.data.jpa.repository.JpaRepository;
import com.yugabyte.springdemo.model.User;

public interface UserRepository extends JpaRepository<User, Long> {

}

This repository can then be used to insert data into the Users table.


@Autowired
private UserRepository userRepository;

...

@PostMapping("/users")
public User createUser(@Valid @RequestBody User user) {
    return userRepository.save(user);
}

Query data

To read data in YugabyteDB, use the out-of-the-box query methods exposed by the repositories.

For example:

@Autowired
private UserRepository userRepository;

@PutMapping("/users/{userId}")
public User updateUser(@PathVariable Long userId,
                                @Valid @RequestBody User userRequest) {
    return userRepository.findById(userId)
            .map(user -> {
                user.setFirstName(userRequest.getFirstName());
                user.setLastName(userRequest.getLastName());
                user.setEmail(userRequest.getEmail());
                return userRepository.save(user);
            }).orElseThrow(() -> new ResourceNotFoundException("User not found with id " + userId));
}

Spring Data JPA repositories provide named queries for adding custom queries to repositories and to update the behavior of built-in queries by using the @Query annotation in the repository implementation.

For example:

import org.springframework.data.jpa.repository.JpaRepository;
import com.yugabyte.springdemo.model.User;

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.emailAddress = ?1")
  User findByEmailAddress(String emailAddress);
}

Transaction and isolation levels

YugabyteDB supports transactions for inserting and querying data from the tables. YugabyteDB supports different isolation levels for maintaining strong consistency for concurrent data access.

By default, CRUD methods on a JPA repository are transactional. For read operations, the transaction configuration readOnly flag is set to true. All others are configured with a plain @Transactional so that the default transaction configuration applies.

The transaction and isolation level of Spring Boot applications can be configured by setting the following properties in the application.properties file.

spring.datasource.hikari.transactionIsolation=TRANSACTION_SERIALIZABLE

Compatibility matrix

Spring Data JPA YugabyteDB Smart Driver Postgres JDBC Driver
2.6.x 42.3.4 42.2.7 or later
2.5.x 42.3.4 42.2.7 or later