Best Practices data databases How-tos Partners prac_eng products Spring spring cloud

Spring Data and YugaByte DB: A Developers Dream

Developers often speak of choosing the right tool for the job. This saying applies to databases. Do the applications require fast response times, transactions, or high availability? Is eventual consistency okay? These and many other questions help you find the appropriate data store.

But what happens when the “right” database is an unfamiliar one? Each data store has a unique access method and feature set. Further, a new database will have a new interface to learn.

Here’s an easy way to circumvent a steep learning curve: Spring Data.

Spring Data is a set of projects in the Spring Framework. The Spring Data family provides a consistent programming model for data access to various data stores, including NoSQL and SQL databases. It offers JDBC for relational databases, Java Persistence API (JPA), or API access to Apache Geode, Apache Cassandra, MongoDB, and many others.

Why is it so great? Like nearly every other Spring project, Spring Data reduces the amount of boilerplate code the developer has to write to interact with these databases.  Instead, the developer can focus on business logic. When a developer uses Spring Data along with Spring Boot, the complexity of a typical application melts away.

So what does that look like? Here’s an example with YugaByte DB, one of my personal favorites.

Using Spring Data with YugaByte DB

YugaByte DB is a high-performance distributed SQL database custom-built for geo-distributed applications running at scale. It's a document store at its heart, with built-in sharding, cross-datacenter replication, and multi-shard ACID transactions. (Does this sound familiar? It’s inspired by Google Spanner.) YugaByte DB can serve both scale-out RDBMS and internet-scale OLTP workloads with low latency, and high availability.

Another reason I love YugaByte DB? It’s uniquely multi-API compatible. It has its own structured query language, YSQL, that’s wire compatible with PostgreSQL. It also includes a semi-relational query language, YCQL, that is API compatible with Apache Cassandra Query Language.

YugaByte DB is a cloud-native database. For instance, YugaByte DB can be reconfigured online with no impact to your applications. These reconfigurations can include changing the underlying machine type, or even the deployed availability zones of the database instance. These changes – and others like it – can be performed without downtime to the client application!

For Spring Data, this means there are multiple options to connect to YugaByte DB: JDBC, JPA, or Spring Data Cassandra. In this example, we will use Spring Boot and Spring Data Cassandra. The example code can be found here. This demonstration introduces the connectivity support of Spring Data and the functionality of providing REST access to YugaByte DB in as few lines of code as possible. (YugaByte has some great examples of more detailed operations in their documentation.)

Configuring Spring Data

The first step to building out the connection with Spring Boot and Spring Data is to build a project. This demo uses the Spring Initializr for initial project setup. (If you write with Spring Framework and you haven’t used Spring Initializr, you really should. It makes the initial project creation so much easier.)

You can use the standard open-source drivers to work with YugaByte DB, as we have here. However, the native YugaByte DB drivers offer several additional features along with higher performance. Let’s look at how to declare the dependency for the native drivers using Maven.

To use the Spring Data Cassandra drivers with YugaByte DB:

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

Using the native YugaByte DB drivers is as simple as swapping out the previous dependency for this one:

<dependency>
 <groupId>com.yugabyte</groupId>
 <artifactId>cassandra-driver-core</artifactId>
 <version>3.2.0-yb-12</version>
</dependency>

Connecting to YugaByte DB

To connect to the cluster, we need to create an application.properties file with the required information. At a minimum, you’ll have to specify the hostname or IP address of one node in the YugaByte DB cluster. For this example, Spring Data has also been configured to auto-create the schema, if it does not already exist. This saves an extra step of logging into the database and executing a create table statement.

$ cat application.properties

spring.data.cassandra.keyspace-name=yugademo
spring.data.cassandra.schema-action=CREATE_IF_NOT_EXISTS
spring.data.cassandra.cluster-name=172.18.0.3

Next, we can create a class that maps to the data that we want to store in the database. In this case, it’s also the source of the auto-generated table definition previously discussed. This code also leverages annotations from Project Lombok, which further reduces the amount of boilerplate code required. Notably, it allows us to skip explicitly defining all our getters and setters.

import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.cassandra.core.mapping.Column;
import org.springframework.data.cassandra.core.mapping.PrimaryKey;
import org.springframework.data.cassandra.core.mapping.Table;

import java.io.Serializable;

@Data
@NoArgsConstructor
@Table(value = "users")
public class User implements Serializable {
  @PrimaryKey("user_id") private Long id;
  @Column("uname") private String username;
  @Column("fname") private String firstname;
  @Column("lname") private String lastname;
}

The main application class is tiny and straightforward. It includes the @EntityScan annotation to identify our persistence object User.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;

@SpringBootApplication
@EntityScan(basePackageClasses = User.class)

public class YugademoApplication {

   public static void main(String[] args) {
       SpringApplication.run(YugademoApplication.class, args);
   }

}

REST APIs

As an example, let us say we want to implement and expose a REST API that retrieves a listing of our users.   

/search/findUsersByIdIsIn?user_id=1001,1002

Under the covers, we want the REST API handler to perform the following query against YugaByte DB using the Spring Data Cassandra connector.

SELECT * FROM users where user_id in (1001,1002);

We can achieve this by creating our final class using the repository support built into Spring Boot and then using Spring Data REST to enable this functionality. Multiple “find” options are automatically offered as methods based on the class you pass to the Repository.  

This class will provide the user with multiple list and search methods to scan the repository. Yet all that is required is calling out the methods desired.  All the backing code is just included as part of a Spring Data project.

import org.springframework.data.repository.CrudRepository;
import java.util.List;

public interface UserRepository extends CrudRepository<User, Long> {
  List<User> findUsersByIdIsIn(List<Long> id);
  User findUserById(long id);
  User findUserByUsername(String username);
  List<User> findUsersByLastnameStartsWith(String lastnamePrefix);
}

Summary: 1 + 1 = 3

This quick walkthrough shows how easy it is to use a variety of data stores when you with Spring Boot and Spring Data.  Database connections and data access specifics are hidden away to empower the developer to focus on the actual business logic instead of the specific details of the database APIs.  

Today, companies are under intense pressure to deliver applications that can support users across the globe. Availability and performance are paramount. YugaByte DB addresses these requirements by delivering a massively-scalable, high-performance, geo-distributed SQL database and combining that with Spring Framework makes the platform even more approachable.

YugaByte is a sponsor at Pivotal’s Spring One Platform Conference this year. Come hear all about their products and lots of customer stories and advice on building incredible software.  Visit https://springoneplatform.io/ and to register now. You can use code: S1P200_DBaskette for a $200 discount!

YugaByte is a Pivotal Partner and has enabled their YugaByte DB on the Pivotal Container Service (PKS) platform to provide private database-as-a-service at extreme scale. They also provide a Pivotal Cloud Foundry Service Broker that enables applications deployed within that environment to easily consume the YugaByte services running within PKS.

YugaByte DB—A Planet-Scale Database for Low Latency Transactional Apps – Spring One Platform

YugaByte DB on Pivotal Container Service (PKS) Tech Talk

YugaByte DB on PKS Installation Documentation