DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Manage Hierarchical Data in MongoDB With Spring
  • Spring Data: Data Auditing Using JaVers and MongoDB
  • Projections/DTOs in Spring Data R2DBC
  • Enterprise RIA With Spring 3, Flex 4 and GraniteDS

Trending

  • Proactive Security in Distributed Systems: A Developer’s Approach
  • A Guide to Auto-Tagging and Lineage Tracking With OpenMetadata
  • AI Agents: A New Era for Integration Professionals
  • The Evolution of Scalable and Resilient Container Infrastructure
  1. DZone
  2. Data Engineering
  3. Databases
  4. Separate Keyspaces With Spring Data Cassandra

Separate Keyspaces With Spring Data Cassandra

Learn about the code needed to allow multiple keyspaces and reasons why you might want to switch from using a single one to using multiple.

By 
Dan Newton user avatar
Dan Newton
·
Oct. 24, 17 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
11.6K Views

Join the DZone community and get the full member experience.

Join For Free

Following on from my previous post, we will look into using multiple keyspaces within an application. This will be a relatively short post due to most of the content being covered in the earlier post, allowing us to focus on the code needed to allow multiple keyspaces and reasons why you might want to switch from using a single one to using multiple.

As mentioned a minute ago, Getting Started With Spring Data Cassandra contains fundamental information required in this post, including dependencies and code snippets that are not shown here.

Firstly, let's start off with why you might want to use multiple keyspaces. When creating a multi-tenant application, there are a few ways to separate each tenant's data from the other — including using a column in the partition key to distinguish each tenant, creating individual tables for each tenant, or using a keyspace for each tenant. Each comes with their advantages and disadvantages; for example, sharing a table between tenants is efficient and easy to use but more active tenants will take over all the key and row caches due to the volume of data they have and the higher number of queries they run.

As mentioned earlier, we will be focusing on using multiple keyspaces, which comes with the advantages of allowing each tenant to have different schemas as well as replication settings. It also comes with the disadvantages of requiring a larger amount of tables when compared to sharing tables between tenants, which in turn increases the number of SSTables and MemTables that are created leading to more memory being used. The advantages and disadvantages described for separate keyspaces are very similar to those of sharing a keyspace but with the exception of not being able to set different replication factors.

Now that there is some context, we can carry on and look at how to implement multiple keyspaces when using Spring Data Cassandra.

There isn't to much code to add upon my previous post, as it just requires a few tweaks to the beans used. That being said, I was hoping it would be a bit more elegant to write but hopefully, the solution I produced is good enough. Anyway, let's get on with looking at the code and you can decide how it looks.

public abstract class CassandraConfig extends AbstractCassandraConfiguration {

  @Value("${cassandra.contactpoints}")
  private String contactPoints;

  @Value("${cassandra.port}")
  private int port;

  @Value("${cassandra.entitypackage}")
  private String entityPackage;

  @Override
  protected String getContactPoints() {
    return contactPoints;
  }

  @Override
  protected int getPort() {
    return port;
  }

  @Override
  public SchemaAction getSchemaAction() {
    return SchemaAction.CREATE_IF_NOT_EXISTS;
  }

  @Override
  public String[] getEntityBasePackages() {
    return new String[] {entityPackage};
  }
}

If you did view my previous post, this class might look familiar. This was originally the main configuration class for an application that was designed to work for a single keyspace. To make the application suitable for multiple keyspaces, I turned it into an abstract class and removed the @Configuration and @EnableCassandraRepositories annotations. It is then extended by other configuration classes, which provide alterations to a few beans to allow them to point to their chosen keyspace. It is worth mentioning that getEntityBasePackages is defined here so that all entities can be defined in a single place where they can be used from whatever keyspaces are defined.

@Configuration
@EnableCassandraRepositories
public class KeyspaceACassandraConfig extends CassandraConfig {

  @Value("${cassandra.keyspace.a}")
  private String keyspace;

  @Override
  public String getKeyspaceName() {
    return keyspace;
  }
}

This configuration class is the smaller of the two shown in this post (the other can be found further below), as I chose to allow it to use the beans defined in AbstractCassandraConfiguration that are created due to extending CassandraConfig. The only configuration actually included in this class is the definition of the keyspace it is using. getKeyspace is used in the session bean created in AbstractCassandraConfiguration, which leads onto an important point about how I have gone about writing this code.

In this post, I chose to tie each keyspace to a session, so as the number of keyspaces increases, a number of sessions running also goes up. This could become problematic when connecting to a lot of keyspaces due to the overhead of running so many independent sessions. It is also possible to use a single session for multiple keyspaces (which I might cover in a later post) by using the CassandraTemplate and specifying the keyspace name in the query. But this requires you to write your own query implementations, as you cannot use the inferred queries that the Spring Data repositories provide.

Continuing on to the other keyspace configuration...

@Configuration
@EnableCassandraRepositories(cassandraTemplateRef = "keyspaceBCassandraTemplate")
public class KeyspaceBCassandraConfig extends CassandraConfig {

  @Value("${cassandra.keyspace.b}")
  private String keyspace;

  @Override
  protected String getKeyspaceName() {
    return keyspace;
  }

  @Override
  @Bean("keyspaceBSession")
  public CassandraSessionFactoryBean session() {
    final CassandraSessionFactoryBean session = super.session();
    session.setKeyspaceName(getKeyspaceName());
    return session;
  }

  @Bean("keyspaceBCassandraTemplate")
  public CassandraAdminOperations cassandraTemplate(
      @Qualifier("keyspaceBSession") final CassandraSessionFactoryBean session) throws Exception {
    return new CassandraAdminTemplate(session.getObject(), cassandraConverter());
  }
}

This class is still pretty similar to the previous configuration but obviously, it has some additions to it. Firstly, it defines two beans, which are also created in AbstractCassandraConfiguration. A new implementation of session is added, which uses the super implementation but provides the bean with a new name of keyspaceBSession instead of session. If this name was not provided, it would get mixed up with the other session used in KeyspaceACassandraConfig. As before, getKeyspaceName is used in the original session method, meaning that it doesn't need to be explicitly set inside this class. The other created bean is the CassandraAdminOperations, which is an interface that CassandraTemplate implements. @Qualifier needs to be used here to specify that the session created here is the one that is used and not the session tied to the other keyspace. The cassandraTemplateRef property inside @EnableCassandraRepositories defines what CassandraTemplate bean is used for all CassandraRepository methods and is crucial for allowing multiple keyspaces to be used. If this property was not set, the repositories would look for a bean named cassandraTemplate, which, in this scenario, is tied to a different keyspace.

After these configuration classes are finished, the only task remaining is creating some repositories. Due to wanting to provide the same methods in each keyspace, a base repository has been created to reduce duplication.

public interface PersonRepository extends CassandraRepository<Person, PersonKey> {

  List<Person> findByKeyFirstName(final String firstName);
}

To be used by the keyspace repositories, for example...

@Repository
public interface KeyspaceAPersonRepository extends PersonRepository {}

This allows the keyspaces to diverge in functionality if required but keeps any shared requirements in a central location. Remember what I mentioned a minute ago — setting the cassandraTemplateRef in the @EnableCassandraRepositories annotation specifies which CassandraTemplate to use, allowing the repositories themselves to be left bare and not require any extra configuration or annotations to make them work.

Now, when each repository is used their queries will be directed towards the correct keyspaces.

That brings us to the end of this shorter post. We looked at how to configure the Spring Data Cassandra repositories to allow multiple keyspaces to be used and briefly touched on why you might want to use more keyspaces within your application. The method used in this post revolved around creating a new session and template for each keyspace, which can be set up without too much extra configuration when compared to using a singular keyspace.

The code used in this post can be found on my GitHub profile.

Keyspace (distributed data store) Spring Data Database Spring Framework Data (computing) POST (HTTP) Session (web analytics) Repository (version control) application

Published at DZone with permission of Dan Newton, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Manage Hierarchical Data in MongoDB With Spring
  • Spring Data: Data Auditing Using JaVers and MongoDB
  • Projections/DTOs in Spring Data R2DBC
  • Enterprise RIA With Spring 3, Flex 4 and GraniteDS

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!