Hands-on using Partition and Clustering



To illustrate the above Partitioning and Clustering concept, we will create an entity/table as a POJO, which will consist of a primary key, which will again be a reference to another POJO. Thus here one table will be created using two POJO where one will act as a primary key of another one.

Create Entity/Table

Lets create both the classes which will be our table.

import org.springframework.data.cassandra.core.mapping.Column;
import org.springframework.data.cassandra.core.mapping.PrimaryKey;
import org.springframework.data.cassandra.core.mapping.Table;
@Table("user")
public class User {
   @PrimaryKey
   private UserKey key;
   @Column("first_name")
   private String firstName;
   private String email;
   public User() {
   }
   public User(UserKey key, String firstName, String email) {
      this.key = key;
      this.firstName = firstName;
      this.email = email;
   }
   public UserKey getKey() {
      return key;
   }
   public void setKey(UserKey key) {
      this.key = key;
   }
   public String getFirstName() {
      return firstName;
   }
   public void setFirstName(String firstName) {
      this.firstName = firstName;
   }
   public String getEmail() {
      return email;
   }
   public void setEmail(String email) {
      this.email = email;
   }
   @Override
   public String toString() {
      return "User [key=" + key + ", firstName=" + firstName + ", email=" + email + "]";
   }
}

Above one is the User table which consist of a primary key called UserKey which is again an Java class and it is called as PrimaryKeyClass. Lets create this as well.

Create UserKey as `PrimaryKeyClass`

import java.io.Serializable;
import java.util.UUID;
import org.springframework.data.cassandra.core.cql.Ordering;
import org.springframework.data.cassandra.core.cql.PrimaryKeyType;
import org.springframework.data.cassandra.core.mapping.PrimaryKeyClass;
import org.springframework.data.cassandra.core.mapping.PrimaryKeyColumn;
@PrimaryKeyClass
public class UserKey implements Serializable {
   @PrimaryKeyColumn(name = "last_name", type = PrimaryKeyType.PARTITIONED)
   private String lastName;
   @PrimaryKeyColumn(name = "salary", ordinal = 0, type = PrimaryKeyType.CLUSTERED)
   private Double salary;
   @PrimaryKeyColumn(name = "user_id", ordinal = 1, ordering = Ordering.DESCENDING)
   private UUID id;
   public UserKey(String lastName, Double salary, UUID id) {
      this.lastName = lastName;
      this.salary = salary;
      this.id = id;
   }
   public String getLastName() {
      return lastName;
   }
   public void setLastName(String lastName) {
      this.lastName = lastName;
   }
   public Double getSalary() {
      return salary;
   }
   public void setSalary(Double salary) {
      this.salary = salary;
   }
   public UUID getId() {
      return id;
   }
   public void setId(UUID id) {
      this.id = id;
   }
   @Override
   public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((id == null) ? 0 : id.hashCode());
      result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
      result = prime * result + ((salary == null) ? 0 : salary.hashCode());
      return result;
   }
   @Override
   public boolean equals(Object obj) {
      if (this == obj)
      return true;
      if (obj == null)
      return false;
      if (getClass() != obj.getClass())
      return false;
      UserKey other = (UserKey) obj;
      if (id == null) {
         if (other.id != null)
         return false;
      } else if (!id.equals(other.id))
      return false;
      if (lastName == null) {
         if (other.lastName != null)
         return false;
      } else if (!lastName.equals(other.lastName))
      return false;
      if (salary == null) {
         if (other.salary != null)
         return false;
      } else if (!salary.equals(other.salary))
      return false;
      return true;
   }
   @Override
   public String toString() {
      return "UserKey [lastName=" + lastName + ", salary=" + salary + ", id=" + id + "]";
   }
}

In the above class we can see the annotation called @PrimaryKeyClass which states that this class will act as a Primary key. The fields of this class is annotated with annotation @PrimaryKeyColumn which simply means the column are the part of Primary Key. The attribute used with these annotations defines the partitioning, clustering and ordering of the records.

For above POJOs we need to write equivalent CQL to create table in Cassandra.

CREATE TABLE user(
   last_name TEXT,
   salary DOUBLE,
   user_id UUID,
   first_name TEXT,
   email TEXT,
   PRIMARY KEY ((last_name), salary, user_id)
) WITH CLUSTERING ORDER BY (salary ASC, user_id DESC);

Create Repository

Now, lets create repository for above table.

import java.util.List;
import org.springframework.data.cassandra.repository.CassandraRepository;
import org.springframework.data.cassandra.repository.Query;
import com.tutorialspoint.entity.User;
import com.tutorialspoint.entity.UserKey;
public interface UserRepository extends CassandraRepository<User, UserKey> {
   List<User> findByKeyLastName(final String lastName);
   List<User> findByKeyLastNameAndKeySalaryGreaterThan(final String firstName, final Double salary);
   @Query(allowFiltering = true)
   List<User> findByFirstName(final String firstName);
}

If we observe the above interface, the generic used with CassandraRepository<User, UserKey> is the table name User and the primary key UserKey. Other than this, the repository consists of some of the derived query methods.

Lets have a look on some CRUD operations using CommandLineRunner.

@Bean
CommandLineRunner commandLineRunner(UserRepository userRepository) {
   return new CommandLineRunner() {
      @Override
      public void run(String... args) throws Exception {
         // Creating entries into the database
         final UserKey key1 = new UserKey("Miller", 81000d, UUID.randomUUID());
         final User user1 = new User(key1, "John", "john@tutorialspoint.com");
         userRepository.insert(user1);
         final UserKey key2 = new UserKey("Monty", 85000d, UUID.randomUUID());
         final User user2 = new User(key2, "Carlos", "carlos@tutorialspoint.com");
         userRepository.insert(user2);
         final UserKey key3 = new UserKey("Benjamin", 95000d, UUID.randomUUID());
         final User user3 = new User(key3, "Franklin", "franklin@tutorialspoint.com");
         userRepository.insert(user3);
         // Fetching entry by last name
         userRepository.findByKeyLastName("Miller").forEach(System.out::println);
         // Find entry by last name and salary greater than
         userRepository.findByKeyLastNameAndKeySalaryGreaterThan("Monty", 81000d).forEach(System.out::println);
         // find entry by first name
         userRepository.findByFirstName("Franklin").forEach(System.out::println);
      }
   };
}
User [key=UserKey [lastName=Miller, salary=81000.0, id=c6344f55-06f2-4edf-8bdb-e55269a0c73a], firstName=John, email=john@tutorialspoint.com]
User [key=UserKey [lastName=Monty, salary=85000.0, id=e8d9100f-1fad-4c93-b735-93fe27d067a7], firstName=Carlos, email=carlos@tutorialspoint.com]
User [key=UserKey [lastName=Benjamin, salary=95000.0, id=fef72f65-ce91-482f-8ed8-e0e39330241f], firstName=Franklin, email=franklin@tutorialspoint.com]
Advertisements