DEV Community

Cover image for Using user-defined types (UDT) with Apache Cassandra in Spring Boot 3.x
Driptaroop Das
Driptaroop Das

Posted on • Originally published at blog.dripto.xyz on

Using user-defined types (UDT) with Apache Cassandra in Spring Boot 3.x

Apache Cassandra is a highly scalable and distributed NoSQL database that is well-suited for handling large amounts of data. One of the powerful features of Cassandra is the ability to use user-defined types (UDT) to model complex data structures. In this blog post, we will learn how to use UDTs with Spring Boot 3.x to interact with a Cassandra database.

Creating the data model in cassandra

First, let's create a simple UDT in Cassandra. You can do this by running the following command in the Cassandra shell (imagining test being the cassandra keyspace):

CREATE TYPE test.address (
    street text,
    city text,
    zip text
);

Enter fullscreen mode Exit fullscreen mode

This creates a UDT called "address" with three fields: street, city, and zip.

Next, we will create a table that uses this UDT. For example, we can create a table called "users" with the following command:

CREATE TABLE test.users (
    id int PRIMARY KEY,
    name text,
    address frozen<address>
);

Enter fullscreen mode Exit fullscreen mode

This table has three columns: id, name, and address. The "address" column is the UDT type here. When defining a user-defined type column, it is best practice to utilize the frozen keyword. This ensures that the user-defined type value cannot be partially updated, but must be completely overwritten. By using the 'frozen' keyword, Cassandra treats the value of the user-defined type as a single, immutable block of data, similar to a binary large object (BLOB).

Setup spring boot 3.x application

Now that we have our UDT and table set up, we can start using them with Spring Boot. Head to start.spring.io to create a spring boot 3.x project with cassandra or add the following dependency to the existing spring boot projects.

Gradle:

  implementation("org.springframework.boot:spring-boot-starter-data-cassandra")

Enter fullscreen mode Exit fullscreen mode

Maven:

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

Enter fullscreen mode Exit fullscreen mode

We also need to configure the Cassandra connection in our application.yml file:

spring:
  data:
    cassandra:
      contact-points: localhost
      port: 9042
      keyspace-name: test

Enter fullscreen mode Exit fullscreen mode

Setup data model in Spring boot application

Once we have the dependency and configuration in place, We also need to create a POJO class that represents our "users" table:

import org.springframework.data.cassandra.core.mapping.PrimaryKey
import org.springframework.data.cassandra.core.mapping.Table

@Table
data class User (
    @PrimaryKey
    val id: Int,
    val name: String,
    /**
     * @CassandraType annotation is not required by default and is redundant. but can be added if requried.
     * @CassandraType(type = CassandraType.Name.UDT, userTypeName = "address")
     */
    val address: Address
)

Enter fullscreen mode Exit fullscreen mode

And a POJO class that represents our address UDT:

import org.springframework.data.cassandra.core.mapping.UserDefinedType

@UserDefinedType("address")
data class Address (
    val street: String,
    val city: String,
    val zip: String
)

Enter fullscreen mode Exit fullscreen mode

we also need to create a Cassandra repository to interact with our users table. For example:

import org.springframework.data.cassandra.repository.CassandraRepository

interface UserRepository : CassandraRepository<User, Int>

Enter fullscreen mode Exit fullscreen mode

Use the repository to call Cassandra

With these classes in place, we can now use the UserRepository to perform CRUD operations on the users table. For example, we can save a new user with:

@Configuration
class App {
    @Bean
    fun runner(userRepository: UserRepository) = ApplicationRunner{
        val user = User(1, "John Doe", Address("Street name", "Berlin", "12345"))
        userRepository.save(user)
    }
}

Enter fullscreen mode Exit fullscreen mode

Conclusion

We hope this tutorial gave you a good idea on how to use user-defined types (UDT) with Apache Cassandra in Spring Boot 3.x. We've shown you how to create a UDT and table in Cassandra, and how to use them with Spring Boot to perform CRUD operations on the table.

Using UDTs can be a powerful way to model complex data structures in Cassandra, and Spring Boot makes it easy to work with these structures in a Java application. With the right configuration and setup, you can easily start using UDTs in your projects to improve the scalability and performance of your data storage.

Be sure to follow best practices when working with UDTs, such as using frozen types and avoiding unnecessary nesting to minimize the complexity. Remember also to keep in mind that UDTs are not supported in some version of Cassandra and not all the drivers support it.

As always, feel free to leave a comment or reach out if you have any questions or need further help. Happy coding!

Top comments (0)